{% extends 'base.html' %}
{% load static %}

{% block title %}对战详情 - {{ battle.id }}{% endblock %}

{% block extra_css %}
<style>
    .page-header {
        background: linear-gradient(135deg, rgba(100, 150, 255, 0.1), rgba(0, 212, 255, 0.1));
        backdrop-filter: blur(10px);
        border: 1px solid rgba(100, 150, 255, 0.2);
        border-radius: 15px;
        padding: 30px;
        margin-bottom: 30px;
        text-align: center;
        box-shadow: 0 8px 32px rgba(100, 150, 255, 0.1);
    }

    .page-header h1 {
        background: linear-gradient(135deg, #6496ff, #00d4ff);
        -webkit-background-clip: text;
        -webkit-text-fill-color: transparent;
        background-clip: text;
        margin: 0;
        font-weight: 600;
        font-size: 2.5rem;
    }

    .container {
        max-width: 1200px;
    }

    .detail-card {
        background: linear-gradient(135deg, rgba(255, 255, 255, 0.1), rgba(255, 255, 255, 0.05));
        backdrop-filter: blur(10px);
        border: 1px solid rgba(100, 150, 255, 0.3);
        border-radius: 20px;
        padding: 30px;
        margin-bottom: 30px;
        box-shadow: 0 8px 32px rgba(0, 0, 0, 0.3);
        transition: all 0.3s ease;
    }

    .detail-card:hover {
        transform: translateY(-5px);
        box-shadow: 0 15px 40px rgba(100, 150, 255, 0.2);
        border-color: rgba(100, 150, 255, 0.5);
    }

    .detail-card h3 {
        color: rgba(255, 255, 255, 0.9);
        margin-bottom: 20px;
        font-weight: 600;
        display: flex;
        align-items: center;
        gap: 10px;
    }

    .detail-card h3 i {
        color: #6496ff;
    }

    .btn-gradient {
        background: linear-gradient(135deg, #6496ff, #00d4ff);
        border: none;
        color: white;
        padding: 12px 30px;
        border-radius: 25px;
        font-weight: 600;
        text-decoration: none;
        display: inline-flex;
        align-items: center;
        gap: 8px;
        transition: all 0.3s ease;
        box-shadow: 0 4px 15px rgba(100, 150, 255, 0.3);
    }

    .btn-gradient:hover {
        transform: translateY(-2px);
        box-shadow: 0 8px 25px rgba(100, 150, 255, 0.4);
        color: white;
        text-decoration: none;
    }

    .btn-outline-gradient {
        background: transparent;
        border: 2px solid rgba(100, 150, 255, 0.6);
        color: rgba(255, 255, 255, 0.9);
        padding: 10px 25px;
        border-radius: 20px;
        font-weight: 500;
        text-decoration: none;
        display: inline-flex;
        align-items: center;
        gap: 8px;
        transition: all 0.3s ease;
        backdrop-filter: blur(5px);
    }

    .btn-outline-gradient:hover {
        background: linear-gradient(135deg, rgba(100, 150, 255, 0.2), rgba(0, 212, 255, 0.2));
        border-color: rgba(100, 150, 255, 0.8);
        color: white;
        text-decoration: none;
        transform: translateY(-2px);
        box-shadow: 0 4px 15px rgba(100, 150, 255, 0.3);
    }

    .status-badge {
        padding: 8px 16px;
        border-radius: 20px;
        font-size: 0.9rem;
        font-weight: 500;
        display: inline-flex;
        align-items: center;
        gap: 8px;
    }

    .status-pending {
        background: linear-gradient(135deg, rgba(255, 193, 7, 0.3), rgba(255, 193, 7, 0.2));
        color: #ffc107;
        border: 1px solid rgba(255, 193, 7, 0.4);
    }

    .status-running {
        background: linear-gradient(135deg, rgba(13, 202, 240, 0.3), rgba(13, 202, 240, 0.2));
        color: #0dcaf0;
        border: 1px solid rgba(13, 202, 240, 0.4);
    }

    .status-finished {
        background: linear-gradient(135deg, rgba(25, 135, 84, 0.3), rgba(25, 135, 84, 0.2));
        color: #198754;
        border: 1px solid rgba(25, 135, 84, 0.4);
    }

    .status-error {
        background: linear-gradient(135deg, rgba(220, 53, 69, 0.3), rgba(220, 53, 69, 0.2));
        color: #dc3545;
        border: 1px solid rgba(220, 53, 69, 0.4);
    }

    .result-win {
        color: #198754;
        font-weight: 600;
    }

    .result-lose {
        color: #dc3545;
        font-weight: 600;
    }

    .result-draw {
        color: #ffc107;
        font-weight: 600;
    }

    .text-muted {
        color: rgba(255, 255, 255, 0.6) !important;
    }

    .table {
        color: rgba(255, 255, 255, 0.9);
    }

    .table th {
        border-color: rgba(100, 150, 255, 0.3);
        background: rgba(100, 150, 255, 0.1);
        color: rgba(255, 255, 255, 0.9);
    }

    .table td {
        border-color: rgba(100, 150, 255, 0.2);
    }

    .alert {
        background: linear-gradient(135deg, rgba(255, 193, 7, 0.2), rgba(255, 193, 7, 0.1));
        border: 1px solid rgba(255, 193, 7, 0.4);
        border-radius: 15px;
        color: rgba(255, 255, 255, 0.9);
        backdrop-filter: blur(10px);
    }

    .alert-info {
        background: linear-gradient(135deg, rgba(13, 202, 240, 0.2), rgba(13, 202, 240, 0.1));
        border-color: rgba(13, 202, 240, 0.4);
    }

    /* 回到顶部悬浮球样式 */
    .back-to-top {
        position: fixed;
        bottom: 30px;
        right: 30px;
        width: 50px;
        height: 50px;
        background: linear-gradient(135deg, #6496ff, #00d4ff);
        border: none;
        border-radius: 50%;
        color: white;
        font-size: 20px;
        cursor: pointer;
        box-shadow: 0 4px 15px rgba(100, 150, 255, 0.4);
        transition: all 0.3s ease;
        z-index: 1000;
        opacity: 0;
        visibility: hidden;
        transform: translateY(20px);
    }

    .back-to-top.show {
        opacity: 1;
        visibility: visible;
        transform: translateY(0);
    }

    .back-to-top:hover {
        transform: translateY(-5px);
        box-shadow: 0 8px 25px rgba(100, 150, 255, 0.6);
        background: linear-gradient(135deg, #7ba7ff, #1ae4ff);
    }

    .back-to-top:active {
        transform: translateY(-2px);
    }

    .alert-success {
        background: linear-gradient(135deg, rgba(25, 135, 84, 0.2), rgba(25, 135, 84, 0.1));
        border-color: rgba(25, 135, 84, 0.4);
    }

    .alert-danger {
        background: linear-gradient(135deg, rgba(220, 53, 69, 0.2), rgba(220, 53, 69, 0.1));
        border-color: rgba(220, 53, 69, 0.4);
    }

    /* Bootstrap Card 深色主题覆盖 */
    .card {
        background: linear-gradient(135deg, rgba(255, 255, 255, 0.1), rgba(100, 150, 255, 0.05)) !important;
        border: 1px solid rgba(100, 150, 255, 0.3) !important;
        border-radius: 15px !important;
        backdrop-filter: blur(10px) !important;
        box-shadow: 0 8px 32px rgba(0, 0, 0, 0.2) !important;
        color: rgba(255, 255, 255, 0.9) !important;
    }

    .card-header {
        background: linear-gradient(135deg, rgba(100, 150, 255, 0.15), rgba(0, 212, 255, 0.1)) !important;
        border-bottom: 1px solid rgba(100, 150, 255, 0.3) !important;
        color: rgba(255, 255, 255, 0.95) !important;
        border-radius: 15px 15px 0 0 !important;
    }

    .card-body {
        background: transparent !important;
        color: rgba(255, 255, 255, 0.9) !important;
    }

    .card h6 {
        color: rgba(255, 255, 255, 0.9) !important;
        font-weight: 600 !important;
    }

    /* 页面特定样式 - 对战详情 */
    .header-title {
        display: flex;
        align-items: center;
        gap: 20px;
        flex-wrap: wrap;
    }

    .header-title h1 {
        background: linear-gradient(135deg, #ffffff, #e0f7ff);
        -webkit-background-clip: text;
        -webkit-text-fill-color: transparent;
        background-clip: text;
        font-weight: 700;
        text-shadow: 0 0 10px rgba(255, 255, 255, 0.3);
        filter: drop-shadow(0 0 8px rgba(255, 255, 255, 0.3));
        margin: 0;
    }

    .battle-status-badge {
        padding: 8px 15px;
        border-radius: 20px;
        font-size: 14px;
        font-weight: bold;
        border: 1px solid rgba(255, 255, 255, 0.3);
        background: rgba(255, 255, 255, 0.1);
        backdrop-filter: blur(10px);
        color: white;
        display: flex;
        align-items: center;
        gap: 8px;
    }

    .battle-status-badge.status-pending {
        background: rgba(255, 193, 7, 0.2);
        border-color: rgba(255, 193, 7, 0.5);
        color: #ffc107;
    }

    .battle-status-badge.status-running {
        background: rgba(0, 123, 255, 0.2);
        border-color: rgba(0, 123, 255, 0.5);
        color: #007bff;
    }

    .battle-status-badge.status-finished {
        background: rgba(40, 167, 69, 0.2);
        border-color: rgba(40, 167, 69, 0.5);
        color: #28a745;
    }

    .battle-status-badge.status-error {
        background: rgba(220, 53, 69, 0.2);
        border-color: rgba(220, 53, 69, 0.5);
        color: #dc3545;
    }



    .breadcrumb-nav {
        display: flex;
        align-items: center;
        gap: 15px;
        margin-bottom: 25px;
        padding: 15px 20px;
        background: linear-gradient(135deg, rgba(100, 150, 255, 0.1), rgba(0, 212, 255, 0.1));
        backdrop-filter: blur(10px);
        border: 1px solid rgba(100, 150, 255, 0.2);
        border-radius: 12px;
        box-shadow: 0 4px 20px rgba(100, 150, 255, 0.1);
    }

    .current-page {
        color: #6496ff;
        font-weight: 600;
        font-size: 1.1rem;
        display: flex;
        align-items: center;
        gap: 8px;
    }

    .current-page i {
        color: #00d4ff;
    }

    .breadcrumb-separator {
        color: rgba(255, 255, 255, 0.5);
        font-size: 1.2rem;
    }

    .refresh-btn {
        background: linear-gradient(135deg, #28a745, #20c997);
        border: none;
        color: white;
        padding: 8px 16px;
        border-radius: 20px;
        font-weight: 500;
        text-decoration: none;
        display: inline-flex;
        align-items: center;
        gap: 6px;
        transition: all 0.3s ease;
        box-shadow: 0 2px 10px rgba(40, 167, 69, 0.3);
        font-size: 0.9rem;
    }

    .refresh-btn:hover {
        transform: translateY(-2px);
        box-shadow: 0 4px 15px rgba(40, 167, 69, 0.4);
        color: white;
        text-decoration: none;
        background: linear-gradient(135deg, #34ce57, #26d0a4);
    }

    .refresh-btn:active {
        transform: translateY(0);
    }

    .refresh-btn i {
        transition: transform 0.3s ease;
    }

    .refresh-btn:hover i {
        transform: rotate(180deg);
    }

    /* 回合折叠功能样式 */
    .round-item {
        transition: all 0.3s ease;
        overflow: hidden;
    }

    .round-header {
        cursor: pointer;
        user-select: none;
        transition: all 0.3s ease;
        padding: 12px 15px;
        background: linear-gradient(135deg, rgba(100, 150, 255, 0.1), rgba(0, 212, 255, 0.05));
        border-radius: 8px;
        border: 1px solid rgba(100, 150, 255, 0.2);
        margin-bottom: 10px;
    }

    .round-header:hover {
        background: linear-gradient(135deg, rgba(100, 150, 255, 0.15), rgba(0, 212, 255, 0.1));
        border-color: rgba(100, 150, 255, 0.3);
        transform: translateY(-1px);
        box-shadow: 0 4px 15px rgba(100, 150, 255, 0.2);
    }

    .round-header .collapse-icon {
        transition: transform 0.3s ease;
        color: #6496ff;
        font-size: 14px;
        margin-right: 8px;
    }

    .round-header.collapsed .collapse-icon {
        transform: rotate(-90deg);
    }

    .round-content {
        transition: all 0.3s ease;
        overflow: hidden;
    }

    .round-content.collapsed {
        max-height: 0;
        opacity: 0;
        margin-top: 0;
        margin-bottom: 0;
        padding-top: 0;
        padding-bottom: 0;
    }

    .round-content.expanded {
        max-height: none;
        opacity: 1;
    }

    .round-summary {
        display: flex;
        align-items: center;
        justify-content: space-between;
        flex-wrap: wrap;
        gap: 10px;
    }

    .round-summary-left {
        display: flex;
        align-items: center;
        gap: 15px;
    }

    .round-summary-right {
        display: flex;
        align-items: center;
        gap: 10px;
        font-size: 0.9rem;
        color: rgba(255, 255, 255, 0.7);
    }

    .round-stats {
        display: flex;
        gap: 15px;
        font-size: 0.85rem;
    }

    .round-stat {
        display: flex;
        align-items: center;
        gap: 4px;
    }

    .round-stat.success {
        color: #28a745;
    }

    .round-stat.failed {
        color: #dc3545;
    }

    .round-stat.error {
        color: #dc3545;
    }

    /* 全部折叠/展开按钮样式 */
    .rounds-control-bar {
        display: flex;
        justify-content: space-between;
        align-items: center;
        margin-bottom: 20px;
        padding: 15px 20px;
        background: linear-gradient(135deg, rgba(100, 150, 255, 0.08), rgba(0, 212, 255, 0.05));
        border-radius: 10px;
        border: 1px solid rgba(100, 150, 255, 0.15);
    }

    .rounds-control-buttons {
        display: flex;
        gap: 10px;
    }

    .control-btn {
        background: linear-gradient(135deg, rgba(100, 150, 255, 0.2), rgba(0, 212, 255, 0.1));
        border: 1px solid rgba(100, 150, 255, 0.3);
        color: rgba(255, 255, 255, 0.9);
        padding: 8px 16px;
        border-radius: 20px;
        font-size: 0.85rem;
        font-weight: 500;
        cursor: pointer;
        transition: all 0.3s ease;
        display: flex;
        align-items: center;
        gap: 6px;
    }

    .control-btn:hover {
        background: linear-gradient(135deg, rgba(100, 150, 255, 0.3), rgba(0, 212, 255, 0.2));
        border-color: rgba(100, 150, 255, 0.5);
        transform: translateY(-1px);
        box-shadow: 0 4px 12px rgba(100, 150, 255, 0.3);
        color: white;
    }

    .control-btn:active {
        transform: translateY(0);
    }

    .control-btn i {
        font-size: 12px;
    }

    /* 战斗统计图标样式 */
    .battle-summary small {
        display: flex;
        align-items: center;
        gap: 6px;
        margin-bottom: 4px;
        padding: 2px 0;
        transition: all 0.2s ease;
    }

    .battle-summary small:hover {
        background: rgba(255, 255, 255, 0.05);
        border-radius: 4px;
        padding: 2px 4px;
    }

    .battle-summary small i {
        width: 14px;
        text-align: center;
        font-size: 12px;
        opacity: 0.9;
    }

    .battle-summary .text-danger {
        color: #ff6b6b !important;
    }

    .battle-summary .text-warning {
        color: #ffd93d !important;
    }

    .battle-summary .text-info {
        color: #74c0fc !important;
    }

    .battle-summary .text-success {
        color: #51cf66 !important;
    }

    .battle-summary .text-primary {
        color: #339af0 !important;
    }

    .battle-summary .text-light-blue {
        color: #87ceeb !important;
    }
</style>
{% endblock %} {% block content %}
<div class="container mt-4">
    <div class="breadcrumb-nav">
        <a href="{% url 'battles:battle_list' %}" class="nav-link">← 返回对战列表</a>
        <span class="breadcrumb-separator">|</span>
        <div class="current-page">
            <i class="fas fa-crosshairs"></i>
            <span>对战详情 #{{ battle.id }}</span>
        </div>
        {% if battle.status == 'running' %}
        <span class="breadcrumb-separator">|</span>
        <button type="button" class="refresh-btn" id="refresh-battle" title="刷新获取最新状态">
            <i class="fas fa-sync-alt"></i>
            <span>刷新</span>
        </button>
        {% endif %}
    </div>

    <div class="row">
        <div class="col-md-12">
            <!-- 对战基本信息已整合到下方的竞技风格对战区域中 -->
            <!-- 玩家信息 -->
            <!-- 对战双方信息 - 竞技风格 -->
            <div class="battle-arena mb-4">
                <div class="row g-0 position-relative">
                    <!-- 玩家1 -->
                    <div class="col-md-5">
                        <div
                            class="player-card player-left{% if battle.status == 'finished' and battle.result == 'player1_win' %} winner-card{% endif %}"
                        >
                            <div class="player-header">
                                <div class="player-avatar">
                                    <i class="fas fa-robot"></i>
                                </div>
                                <div class="player-info">
                                    <h4
                                        class="player-name{% if battle.status == 'finished' and battle.result == 'player1_win' %} winner-name{% endif %}"
                                    >
                                        {{ battle.player1.username }}
                                    </h4>
                                    <div
                                        class="player-badge red{% if battle.status == 'finished' and battle.result == 'player1_win' %} winner-badge{% endif %}"
                                    >
                                        PLAYER 1{% if battle.status == 'finished' and battle.result == 'player1_win' %} -
                                        获胜者{% endif %}
                                    </div>
                                </div>
                            </div>
                            <div class="player-stats">
                                <div class="stat-item">
                                    <span class="stat-label">代码</span>
                                    <span class="stat-value">{{ battle.player1_code.title }}</span>
                                </div>
                                <div class="stat-item">
                                    <span class="stat-label">语言</span>
                                    <span class="stat-value">
                                        <span class="lang-badge">{{ battle.player1_code.language }}</span>
                                    </span>
                                </div>
                                {% if battle.status == 'finished' %}
                                <div class="stat-item score-item">
                                    <span class="stat-label">得分</span>
                                    <span class="score-value red">{{ battle.player1_score }}</span>
                                </div>
                                {% endif %}
                                <!-- 战斗结果统计 - 对于进行中和已完成的对战都显示 -->
                                {% if battle.status == 'running' or battle.status == 'finished' %}
                                <div class="stat-item battle-stats" id="player1-battle-stats">
                                    <span class="stat-label">{% if battle.status == 'running' %}实时统计{% else %}战斗统计{% endif %}</span>
                                    <span class="stat-value">
                                        <span class="battle-summary" id="player1-battle-summary">
                                            {% if battle.player1_stats %}
                                            <small class="d-block"><i class="fas fa-fire text-danger"></i> 击杀: {{ battle.player1_stats.stats.kills|default:0 }}</small>
                                            <small class="d-block"><i class="fas fa-skull text-warning"></i> 死亡: {{ battle.player1_stats.stats.deaths|default:0 }}</small>
                                            <small class="d-block"><i class="fas fa-bolt text-info"></i> 伤害: {{ battle.player1_stats.stats.totalDamageDealt|default:0 }}</small>
                                            <small class="d-block"><i class="fas fa-pills text-success"></i> 治疗: {{ battle.player1_stats.stats.totalHealing|default:0 }}</small>
                                            <small class="d-block"><i class="fas fa-heart text-danger"></i> 基地血量: {{ battle.player1_stats.baseHealth|default:0 }}</small>
                                            <small class="d-block"><i class="fas fa-gem text-light-blue"></i> RMB: {{ battle.player1_stats.rmb|default:0 }}</small>
                                            {% else %}
                                            <small class="text-muted">暂无数据</small>
                                            {% endif %}
                                        </span>
                                    </span>
                                </div>
                                {% endif %}
                            </div>
                        </div>
                    </div>

                    <!-- 中央VS区域 - 增强版 -->
                    <div class="col-md-2 d-flex align-items-center justify-content-center">
                        <div class="vs-section-enhanced">
                            <!-- 战斗类型信息 -->
                            <div class="battle-type-section">
                                <div class="battle-type-display">
                                    <i class="fas fa-trophy"></i> {{ battle.get_battle_type_display }}
                                </div>
                            </div>

                            <!-- 对战状态指示器 -->
                            <div class="battle-status-indicator">
                                {% if battle.status == 'pending' %}
                                <span class="status-badge status-pending"><i class="fas fa-clock"></i> 等待中</span>
                                {% elif battle.status == 'running' %}
                                <span class="status-badge status-running"><i class="fas fa-play"></i> 进行中</span>
                                {% elif battle.status == 'finished' %}
                                <span class="status-badge status-finished"><i class="fas fa-check"></i> 已完成</span>

                                {% elif battle.status == 'error' %}
                                <span class="status-badge status-error"><i class="fas fa-exclamation"></i> 错误</span>
                                {% endif %}
                            </div>

                            <!-- 主VS圆圈 -->
                            <div class="vs-circle-enhanced">
                                <div class="vs-inner">
                                    <span class="vs-text">VS</span>
                                    <div class="battle-id">#{{ battle.id }}</div>
                                </div>
                            </div>

                            <!-- 对战结果显示 -->
                            {% if battle.status == 'finished' %}
                            <div class="battle-result">
                                {% if battle.result == 'player1_win' %}
                                <div class="winner-indicator left-win">
                                    <i class="fas fa-trophy"></i> {{ battle.player1.username }} 获胜
                                </div>
                                {% elif battle.result == 'player2_win' %}
                                <div class="winner-indicator right-win">
                                    <i class="fas fa-trophy"></i> {{ battle.player2.username }} 获胜
                                </div>
                                {% elif battle.result == 'draw' %}
                                <div class="winner-indicator draw"><i class="fas fa-handshake"></i> 平局</div>
                                {% endif %}
                            </div>
                            {% endif %}

                            <!-- 对战时间信息 -->
                            <div class="battle-time-info">
                                {% if battle.status == 'finished' and battle.get_duration %}
                                <div class="duration-display"><i class="fas fa-stopwatch"></i> {{ battle.get_duration }}</div>
                                {% endif %}

                                <!-- 回合数显示 -->
                                {% if battle.status == 'running' %}
                                <div class="rounds-display">
                                    <i class="fas fa-layer-group"></i> 第 {{ rounds_count }} 回合
                                </div>
                                {% elif battle.total_rounds %}
                                <div class="rounds-display">
                                    <i class="fas fa-layer-group"></i> {{ battle.total_rounds }} 回合
                                </div>
                                {% endif %}

                                {% if battle.map_config.map %}
                                <div class="map-display"><i class="fas fa-map"></i> {{ battle.map_config.map }} 地图</div>
                                {% endif %}
                            </div>

                            <!-- 动态火花效果 -->
                            <div class="battle-sparks-enhanced">
                                <i class="fas fa-bolt spark-1"></i>
                                <i class="fas fa-bolt spark-2"></i>
                                <i class="fas fa-bolt spark-3"></i>
                                <i class="fas fa-star spark-4"></i>
                                <i class="fas fa-star spark-5"></i>
                            </div>
                        </div>
                    </div>

                    <!-- 玩家2 -->
                    <div class="col-md-5">
                        <div
                            class="player-card player-right{% if battle.status == 'finished' and battle.result == 'player2_win' %} winner-card{% endif %}"
                        >
                            <div class="player-header player-header-right">
                                <div class="player-avatar">
                                    <i class="fas fa-robot"></i>
                                </div>
                                <div class="player-info player-info-right">
                                    <h4
                                        class="player-name{% if battle.status == 'finished' and battle.result == 'player2_win' %} winner-name{% endif %}"
                                    >
                                        {{ battle.player2.username }}
                                    </h4>
                                    <div
                                        class="player-badge blue{% if battle.status == 'finished' and battle.result == 'player2_win' %} winner-badge{% endif %}"
                                    >
                                        PLAYER 2{% if battle.status == 'finished' and battle.result == 'player2_win' %} -
                                        获胜者{% endif %}
                                    </div>
                                </div>
                            </div>
                            <div class="player-stats player-stats-right">
                                <div class="stat-item stat-item-right">
                                    <span class="stat-label">代码</span>
                                    <span class="stat-value">{{ battle.player2_code.title }}</span>
                                </div>
                                <div class="stat-item stat-item-right">
                                    <span class="stat-label">语言</span>
                                    <span class="stat-value">
                                        <span class="lang-badge">{{ battle.player2_code.language }}</span>
                                    </span>
                                </div>
                                {% if battle.status == 'finished' %}
                                <div class="stat-item score-item stat-item-right">
                                    <span class="stat-label">得分</span>
                                    <span class="score-value blue">{{ battle.player2_score }}</span>
                                </div>
                                {% endif %}
                                <!-- 战斗结果统计 - 对于进行中和已完成的对战都显示 -->
                                {% if battle.status == 'running' or battle.status == 'finished' %}
                                <div class="stat-item stat-item-right battle-stats" id="player2-battle-stats">
                                    <span class="stat-label">{% if battle.status == 'running' %}实时统计{% else %}战斗统计{% endif %}</span>
                                    <span class="stat-value">
                                        <span class="battle-summary" id="player2-battle-summary">
                                            {% if battle.player2_stats %}
                                            <small class="d-block"><i class="fas fa-fire text-danger"></i> 击杀: {{ battle.player2_stats.stats.kills|default:0 }}</small>
                                            <small class="d-block"><i class="fas fa-skull text-warning"></i> 死亡: {{ battle.player2_stats.stats.deaths|default:0 }}</small>
                                            <small class="d-block"><i class="fas fa-bolt text-info"></i> 伤害: {{ battle.player2_stats.stats.totalDamageDealt|default:0 }}</small>
                                            <small class="d-block"><i class="fas fa-pills text-success"></i> 治疗: {{ battle.player2_stats.stats.totalHealing|default:0 }}</small>
                                            <small class="d-block"><i class="fas fa-heart text-danger"></i> 基地血量: {{ battle.player2_stats.baseHealth|default:0 }}</small>
                                            <small class="d-block"><i class="fas fa-gem text-light-blue"></i> RMB: {{ battle.player2_stats.rmb|default:0 }}</small>
                                            {% else %}
                                            <small class="text-muted">暂无数据</small>
                                            {% endif %}
                                        </span>
                                    </span>
                                </div>
                                {% endif %}
                            </div>
                        </div>
                    </div>
                </div>
            </div>

            <!-- 获胜信息显示容器 -->
            {% if battle.status == 'finished' and rounds_count > 0 %}
            <div id="victory-message-section" class="mb-4" style="display: none;">
                <div class="detail-card" style="background: linear-gradient(135deg, rgba(255, 193, 7, 0.15), rgba(255, 193, 7, 0.05)); border-color: rgba(255, 193, 7, 0.4);">
                    <div class="d-flex align-items-center justify-content-center">
                        <div class="text-center">
                            <h4 class="mb-2" style="color: #ffc107; font-weight: 600;">
                                <i class="fas fa-trophy"></i> 对战结果
                            </h4>
                            <p id="victory-message-text" class="mb-0" style="color: #ffc107; font-size: 1.1rem; font-weight: 500;">
                                <!-- 获胜信息将通过JavaScript动态加载 -->
                            </p>
                        </div>
                    </div>
                </div>
            </div>
            {% endif %}

            <!-- 嵌入式回放功能 -->
            {% if battle.status == 'finished' and rounds_count > 0 %}
            <div id="replay-section" class="mb-4">
                <!-- 回放控制器 -->
                <div
                    class="d-flex justify-content-between align-items-center mb-3 p-3 rounded"
                    style="
                        background: linear-gradient(135deg, rgba(100, 150, 255, 0.1), rgba(0, 212, 255, 0.05));
                        border: 1px solid rgba(100, 150, 255, 0.3);
                        backdrop-filter: blur(10px);
                    "
                >
                    <div class="d-flex align-items-center">
                        <h5 class="mb-0 me-3"><i class="fas fa-play-circle text-primary"></i> 对战回放</h5>
                        <small class="text-muted">回放控制由游戏内处理</small>
                        <div class="ms-3" id="timeout-message" style="display: none;"><span class="text-danger fw-bold" style="animation: blink 1.5s infinite;"><i class="fas fa-exclamation-circle"></i> 你好, 加载超时请刷新页面...</span></div>
                    </div>
                    <style>
                        @keyframes blink {
                            0% { opacity: 1; }
                            50% { opacity: 0.5; }
                            100% { opacity: 1; }
                        }
                    </style>
                    <div class="d-flex gap-2">
                        <button type="button" class="btn btn-primary" id="btn-start-replay" disabled>
                            <i class="fas fa-spinner fa-spin"></i> 加载中...
                        </button>
                        <button type="button" class="btn btn-outline-secondary" id="btn-fullscreen" title="全屏">
                            <i class="fas fa-expand"></i> 全屏
                        </button>
                        <button
                            type="button"
                            class="btn btn-outline-secondary"
                            id="btn-exit-fullscreen"
                            style="display: none"
                            title="退出全屏"
                        >
                            <i class="fas fa-compress"></i> 退出全屏
                        </button>
                    </div>
                </div>

                <!-- Cocos游戏画面 -->
                <div class="position-relative">
                    <div
                        class="battle-frame"
                        id="battle-frame"
                        style="
                            background: #2c3e50;
                            border-radius: 8px;
                            overflow: hidden;
                            box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
                        "
                    >
                        <iframe
                            id="replay-iframe"
                            src="/static/battle/index.html"
                            width="100%"
                            height="600px"
                            frameborder="0"
                            title="战斗回放界面"
                            style="border-radius: 8px"
                        ></iframe>
                    </div>
                </div>
            </div>
            {% endif %}

            <!-- 执行统计和日志操作区域 -->
            {% if battle.status == 'finished' %}
            <div class="detail-card mb-4">
                <div class="d-flex justify-content-between align-items-center mb-3">
                    <h5 class="mb-0"><i class="fas fa-chart-line text-primary"></i> 命令执行统计</h5>
                    <div class="d-flex gap-2">
                        <button
                            type="button"
                            class="btn btn-outline-primary btn-xs"
                            id="btn-view-execution-details"
                            style="font-size: 0.75rem; padding: 4px 8px"
                        >
                            <i class="fas fa-eye" style="font-size: 0.7rem"></i> 查看失败命令详情
                        </button>
                        <button
                            type="button"
                            class="btn btn-outline-info btn-xs"
                            id="btn-download-battle-report"
                            style="font-size: 0.75rem; padding: 4px 8px"
                        >
                            <i class="fas fa-file-alt" style="font-size: 0.7rem"></i> 下载战报
                        </button>
                        <button
                            type="button"
                            class="btn btn-outline-success btn-xs"
                            id="btn-download-log"
                            style="font-size: 0.75rem; padding: 4px 8px"
                        >
                            <i class="fas fa-download" style="font-size: 0.7rem"></i> 下载日志
                        </button>
                    </div>
                </div>

                <!-- 执行统计概览 -->
                <div class="row" id="execution-stats-overview">
                    <div class="col-md-6">
                        <div class="stats-card player1-stats">
                            <h6 class="text-danger"><i class="fas fa-user"></i> {{ battle.player1.username }}</h6>
                            <div id="player1-detailed-stats">加载中...</div>
                        </div>
                    </div>
                    <div class="col-md-6">
                        <div class="stats-card player2-stats">
                            <h6 class="text-primary"><i class="fas fa-user"></i> {{ battle.player2.username }}</h6>
                            <div id="player2-detailed-stats">加载中...</div>
                        </div>
                    </div>
                </div>

                <!-- 失败命令详情（默认隐藏） -->
                <div class="mt-3" id="failed-commands-section" style="display: none">
                    <h6><i class="fas fa-exclamation-triangle text-warning"></i> 失败命令详情</h6>
                    <div class="row">
                        <div class="col-md-6">
                            <div class="failed-commands-list" id="player1-failed-commands"></div>
                        </div>
                        <div class="col-md-6">
                            <div class="failed-commands-list" id="player2-failed-commands"></div>
                        </div>
                    </div>
                </div>
            </div>
            {% endif %}

            <!-- 失败命令详情模态框 -->
            <div
                class="modal fade"
                id="executionDetailsModal"
                tabindex="-1"
                aria-labelledby="executionDetailsModalLabel"
                aria-hidden="true"
            >
                <div class="modal-dialog modal-xl">
                    <div class="modal-content">
                        <div class="modal-header">
                            <h5 class="modal-title" id="executionDetailsModalLabel">
                                <i class="fas fa-exclamation-triangle text-warning"></i> 失败命令详情
                            </h5>
                            <button
                                type="button"
                                class="btn-close"
                                data-bs-dismiss="modal"
                                data-dismiss="modal"
                                aria-label="Close"
                            >
                                <span aria-hidden="true">&times;</span>
                            </button>
                        </div>
                        <div class="modal-body">
                            <div class="row">
                                <div class="col-md-6">
                                    <h6 class="text-danger">玩家1失败命令</h6>
                                    <div class="failed-commands-list" id="player1-failed-commands-modal"></div>
                                </div>
                                <div class="col-md-6">
                                    <h6 class="text-primary">玩家2失败命令</h6>
                                    <div class="failed-commands-list" id="player2-failed-commands-modal"></div>
                                </div>
                            </div>
                        </div>
                        <div class="modal-footer">
                            <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">关闭</button>
                            <button type="button" class="btn btn-primary" id="exportFailedCommandsBtn">
                                <i class="fas fa-download"></i> 导出失败命令
                            </button>
                        </div>
                    </div>
                </div>
            </div>

            <!-- 回合详情 -->
            {% if rounds_count > 0 %}
            <div class="card">
                <div class="card-header d-flex justify-content-between align-items-center">
                    <h6 class="mb-0"><i class="fas fa-play-circle"></i> 回合时间轴 (共 <span id="total-rounds-display">{{ rounds_count }}</span> 回合)</h6>
                    <div class="d-flex align-items-center gap-2"></div>
                </div>
                <div class="card-body">
                    <!-- 简化的回合区间选择器 -->
                    <div class="simple-range-selector mb-4">
                        <div class="d-flex justify-content-between align-items-center mb-3">
                            <h6 class="mb-0"><i class="fas fa-sliders-h"></i> 回合区间选择</h6>
                            <span class="badge bg-info" id="range-display">回合 1 - <span id="max-rounds-display">{{ rounds_count }}</span></span>
                        </div>

                        <!-- 简化的输入控制 -->
                        <div class="row g-2 mb-3">
                            <div class="col-md-4">
                                <label class="form-label small">起始回合</label>
                                <input
                                    type="number"
                                    class="form-control form-control-sm"
                                    id="start-round"
                                    min="1"
                                    max="{{ rounds_count }}"
                                    value="1"
                                />
                            </div>
                            <div class="col-md-4">
                                <label class="form-label small">结束回合</label>
                                <input
                                    type="number"
                                    class="form-control form-control-sm"
                                    id="end-round"
                                    min="1"
                                    max="{{ rounds_count }}"
                                    value="{{ rounds_count }}"
                                />
                            </div>
                            <div class="col-md-4 d-flex align-items-end">
                                <button class="btn btn-sm btn-primary me-2" id="apply-range">
                                    <i class="fas fa-check"></i> 应用
                                </button>
                                <button class="btn btn-sm btn-outline-secondary" id="reset-range">
                                    <i class="fas fa-undo"></i> 重置
                                </button>
                            </div>
                        </div>

                        <!-- 简化的双滑块 -->
                        <div class="simple-range-slider">
                            <input
                                type="range"
                                id="start-slider"
                                class="range-input start"
                                min="1"
                                max="{{ rounds_count }}"
                                value="1"
                            />
                            <input
                                type="range"
                                id="end-slider"
                                class="range-input end"
                                min="1"
                                max="{{ rounds_count }}"
                                value="{{ rounds_count }}"
                            />
                            <div class="range-track">
                                <div class="range-fill" id="range-fill"></div>
                            </div>
                        </div>

                        <div class="d-flex justify-content-between mt-2">
                            <small class="text-muted">回合 1</small>
                            <small class="text-muted">回合 {{ rounds_count }}</small>
                        </div>
                    </div>

                    <!-- 搜索和过滤 -->
                    <div class="row mb-3">
                        <div class="col-md-6">
                            <select
                                class="form-select form-select-sm"
                                id="command-type-filter"
                            >
                                <option value="all">全部命令类型</option>
                                <option value="move">移动 (move)</option>
                                <option value="attack">攻击 (attack)</option>
                                <option value="build">建造 (build)</option>
                                <option value="swap">生产 (swap)</option>
                                <option value="heal">治疗 (heal)</option>
                                <option value="collect">采集 (collect)</option>
                            </select>
                        </div>
                        <div class="col-md-6">
                            <select class="form-select form-select-sm" id="round-filter">
                                <option value="">显示所有回合</option>
                                <option value="error-or-failed">全部报错或有失败回合</option>
                                <option value="player1-error-or-failed">玩家1报错或有失败回合</option>
                                <option value="player2-error-or-failed">玩家2报错或有失败回合</option>
                            </select>
                        </div>
                    </div>

                    <!-- 区间回合列表容器 -->
                    <div id="range-rounds-container">
                        <div class="range-rounds-header mb-3">
                            <div class="d-flex justify-content-between align-items-center">
                                <h6 class="mb-0"><i class="fas fa-list"></i> 选定区间回合详情</h6>
                                <div class="range-summary">
                                    <span class="text-muted small" id="range-summary-text">共 1 个回合</span>
                                </div>
                            </div>
                        </div>

                        <!-- 回合控制栏 -->
                        <div class="rounds-control-bar" id="rounds-control-bar" style="display: none;">
                            <div class="rounds-info">
                                <span class="text-muted small">
                                    <i class="fas fa-info-circle"></i>
                                    点击回合标题可折叠/展开详情
                                </span>
                            </div>
                            <div class="rounds-control-buttons">
                                <button type="button" class="control-btn" id="expand-all-rounds">
                                    <i class="fas fa-expand-arrows-alt"></i>
                                    <span>展开全部</span>
                                </button>
                                <button type="button" class="control-btn" id="collapse-all-rounds">
                                    <i class="fas fa-compress-arrows-alt"></i>
                                    <span>折叠全部</span>
                                </button>
                            </div>
                        </div>

                        <div id="range-rounds-list">
                            <div id="rounds-loading" class="text-center py-3">
                                <div class="spinner-border spinner-border-sm" role="status">
                                    <span class="visually-hidden">加载中...</span>
                                </div>
                                <div class="ms-2">正在异步加载回合数据...</div>
                            </div>
                        </div>
                    </div>
                </div>
            </div>
            {% endif %}
        </div>
    </div>
</div>

{% if rounds_count > 0 %}
<!-- 预处理回放数据 - 现在通过异步加载 -->
<div id="rounds-data" style="display: none;"></div>
{{ battle_data|json_script:"battle-data" }}
<!-- 引入BattleBridge -->
<script src="{% static 'js/battleBridge.js' %}"></script>

<!-- 全屏样式和竞技风格样式 -->
<style>
    /* iframe全屏模式下的样式 */
    #replay-iframe:fullscreen {
        width: 100vw !important;
        height: 100vh !important;
        background: #000 !important;
        border-radius: 0 !important;
        border: none !important;
    }

    #replay-iframe:-webkit-full-screen {
        width: 100vw !important;
        height: 100vh !important;
        background: #000 !important;
        border-radius: 0 !important;
        border: none !important;
    }

    #replay-iframe:-moz-full-screen {
        width: 100vw !important;
        height: 100vh !important;
        background: #000 !important;
        border-radius: 0 !important;
        border: none !important;
    }

    #replay-iframe:-ms-fullscreen {
        width: 100vw !important;
        height: 100vh !important;
        background: #000 !important;
        border-radius: 0 !important;
        border: none !important;
    }

    /* 竞技风格对战界面 */
    .battle-arena {
        background: linear-gradient(135deg, #1a1a2e 0%, #16213e 50%, #0f3460 100%);
        border-radius: 20px;
        padding: 30px;
        box-shadow: 0 20px 40px rgba(0, 0, 0, 0.3);
        position: relative;
        overflow: hidden;
    }

    .battle-arena::before {
        content: '';
        position: absolute;
        top: 0;
        left: 0;
        right: 0;
        bottom: 0;
        background: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100"><defs><pattern id="grid" width="10" height="10" patternUnits="userSpaceOnUse"><path d="M 10 0 L 0 0 0 10" fill="none" stroke="%23ffffff" stroke-width="0.5" opacity="0.1"/></pattern></defs><rect width="100" height="100" fill="url(%23grid)"/></svg>');
        pointer-events: none;
    }

    /* 模态框美化样式 */
    #executionDetailsModal .modal-dialog {
        max-width: 90vw;
        height: 92vh;
        margin: 1vh auto;
    }

    #executionDetailsModal .modal-content {
        height: 100%;
        background: linear-gradient(135deg, #1a1a2e 0%, #16213e 50%, #0f3460 100%);
        border: 1px solid rgba(255, 215, 0, 0.3);
        border-radius: 15px;
        box-shadow: 0 25px 50px rgba(0, 0, 0, 0.5);
        backdrop-filter: blur(20px);
    }

    #executionDetailsModal .modal-header {
        background: linear-gradient(135deg, rgba(255, 215, 0, 0.2), rgba(255, 215, 0, 0.1));
        border-bottom: 1px solid rgba(255, 215, 0, 0.3);
        border-radius: 15px 15px 0 0;
        padding: 12px 20px;
    }

    #executionDetailsModal .modal-title {
        color: #ffd700;
        font-weight: 600;
        font-size: 1.1rem;
        text-shadow: 0 2px 4px rgba(0, 0, 0, 0.5);
    }

    #executionDetailsModal .btn-close {
        background: rgba(255, 255, 255, 0.1);
        border: 1px solid rgba(255, 255, 255, 0.2);
        border-radius: 50%;
        width: 28px;
        height: 28px;
        opacity: 0.8;
        transition: all 0.3s ease;
        display: flex;
        align-items: center;
        justify-content: center;
        color: #ffffff;
        font-size: 14px;
        font-weight: bold;
        padding: 0;
    }

    #executionDetailsModal .btn-close:hover {
        background: rgba(255, 255, 255, 0.2);
        border-color: rgba(255, 255, 255, 0.4);
        opacity: 1;
        transform: scale(1.1);
        color: #ffffff;
    }

    #executionDetailsModal .btn-close span {
        line-height: 1;
        font-size: 16px;
    }

    #executionDetailsModal .modal-body {
        padding: 20px;
        overflow-y: auto;
        flex: 1;
        background: rgba(0, 0, 0, 0.2);
    }

    #executionDetailsModal .modal-footer {
        background: linear-gradient(135deg, rgba(255, 215, 0, 0.1), rgba(255, 215, 0, 0.05));
        border-top: 1px solid rgba(255, 215, 0, 0.3);
        border-radius: 0 0 15px 15px;
        padding: 8px 20px;
    }

    #executionDetailsModal .failed-commands-list {
        max-height: 70vh;
        overflow-y: auto;
        padding-right: 10px;
    }

    #executionDetailsModal .failed-commands-list::-webkit-scrollbar {
        width: 8px;
    }

    #executionDetailsModal .failed-commands-list::-webkit-scrollbar-track {
        background: rgba(255, 255, 255, 0.1);
        border-radius: 4px;
    }

    #executionDetailsModal .failed-commands-list::-webkit-scrollbar-thumb {
        background: linear-gradient(135deg, #ffd700, #ffed4e);
        border-radius: 4px;
    }

    #executionDetailsModal .failed-commands-list::-webkit-scrollbar-thumb:hover {
        background: linear-gradient(135deg, #ffed4e, #ffd700);
    }

    #executionDetailsModal .failed-command-item {
        background: rgba(255, 255, 255, 0.05);
        border: 1px solid rgba(255, 215, 0, 0.2);
        border-radius: 10px;
        margin-bottom: 10px;
        padding: 15px;
        transition: all 0.3s ease;
        backdrop-filter: blur(10px);
    }

    #executionDetailsModal .failed-command-item:hover {
        background: rgba(255, 255, 255, 0.08);
        border-color: rgba(255, 215, 0, 0.4);
        transform: translateY(-2px);
        box-shadow: 0 8px 25px rgba(255, 215, 0, 0.2);
    }

    #executionDetailsModal .failed-command-header {
        display: flex;
        justify-content: space-between;
        align-items: center;
        margin-bottom: 10px;
        padding-bottom: 8px;
        border-bottom: 1px solid rgba(255, 215, 0, 0.2);
    }

    #executionDetailsModal .error-message {
        color: #ff6b6b;
        font-weight: 400;
        padding: 2px 8px 2px 8px;
        border-radius: 6px;
        border-left: 3px;
        word-wrap: break-word;
        word-break: break-word;
        white-space: pre-wrap;
        line-height: 1.4;
    }

    #executionDetailsModal .json-display,
    #executionDetailsModal .raw-display {
        background: rgba(0, 0, 0, 0.3);
        border: 1px solid rgba(255, 215, 0, 0.2);
        border-radius: 8px;
        padding: 12px;
        margin-top: 8px;
        font-family: 'Consolas', 'Monaco', 'Courier New', monospace;
        font-size: 0.85rem;
        line-height: 1.3;
        color: #e8e8e8;
        overflow-x: auto;
        max-height: 500px;
        overflow-y: auto;
    }

    #executionDetailsModal .json-display code,
    #executionDetailsModal .raw-display code {
        color: #e8e8e8;
        background: none;
        padding: 0;
        font-size: inherit;
    }

    #executionDetailsModal h6 {
        color: #ffd700;
        font-weight: 600;
        margin-bottom: 20px;
        padding-bottom: 10px;
        border-bottom: 2px solid rgba(255, 215, 0, 0.3);
        text-shadow: 0 2px 4px rgba(0, 0, 0, 0.5);
    }

    #executionDetailsModal .btn {
        border-radius: 6px;
        padding: 6px 12px;
        font-weight: 500;
        font-size: 0.8rem;
        transition: all 0.3s ease;
        text-shadow: 0 1px 2px rgba(0, 0, 0, 0.3);
    }

    #executionDetailsModal .btn-primary {
        background: linear-gradient(135deg, #ffd700, #ffed4e);
        border: 1px solid #ffd700;
        color: #1a1a2e;
    }

    #executionDetailsModal .btn-primary:hover {
        background: linear-gradient(135deg, #ffed4e, #fff59d);
        border-color: #ffed4e;
        transform: translateY(-2px);
        box-shadow: 0 8px 25px rgba(255, 215, 0, 0.3);
    }

    #executionDetailsModal .btn-secondary {
        background: rgba(255, 255, 255, 0.1);
        border: 1px solid rgba(255, 255, 255, 0.2);
        color: #ffffff;
    }

    #executionDetailsModal .btn-secondary:hover {
        background: rgba(255, 255, 255, 0.2);
        border-color: rgba(255, 255, 255, 0.3);
        transform: translateY(-2px);
    }

    .player-card {
        background: rgba(255, 255, 255, 0.05);
        backdrop-filter: blur(10px);
        border-radius: 15px;
        padding: 25px;
        border: 1px solid rgba(255, 255, 255, 0.1);
        transition: all 0.3s ease;
        position: relative;
        overflow: hidden;
    }

    .player-card::before {
        content: '';
        position: absolute;
        top: 0;
        left: -100%;
        width: 100%;
        height: 100%;
        background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.1), transparent);
        transition: left 0.5s ease;
    }

    .player-card:hover::before {
        left: 100%;
    }

    .player-left {
        border-left: 4px solid #dc3545;
        transform: perspective(1000px) rotateY(5deg);
    }

    .player-right {
        border-right: 4px solid #007bff;
        transform: perspective(1000px) rotateY(-5deg);
    }

    /* 获胜者卡片特殊效果 */
    .winner-card {
        border: 3px solid #ffd700 !important;
        box-shadow: 0 0 30px rgba(255, 215, 0, 0.6), 0 0 60px rgba(255, 215, 0, 0.4) !important;
        background: linear-gradient(135deg, rgba(255, 215, 0, 0.1), rgba(255, 215, 0, 0.05)) !important;
        animation: winnerGlow 2s ease-in-out infinite;
        position: relative;
    }

    .winner-card::after {
        content: '🏆';
        position: absolute;
        top: 30px;
        right: 80px;
        font-size: 2rem;
        background: linear-gradient(45deg, #ffd700, #ffed4e);
        border-radius: 50%;
        width: 50px;
        height: 50px;
        display: flex;
        align-items: center;
        justify-content: center;
        box-shadow: 0 4px 15px rgba(255, 215, 0, 0.5);
        animation: trophyBounce 1.5s ease-in-out infinite;
    }

    @keyframes winnerGlow {
        0%,
        100% {
            box-shadow: 0 0 30px rgba(255, 215, 0, 0.6), 0 0 60px rgba(255, 215, 0, 0.4);
        }
        50% {
            box-shadow: 0 0 40px rgba(255, 215, 0, 0.8), 0 0 80px rgba(255, 215, 0, 0.6);
        }
    }

    @keyframes trophyBounce {
        0%,
        100% {
            transform: translateY(0) scale(1);
        }
        50% {
            transform: translateY(-5px) scale(1.1);
        }
    }

    .player-header {
        display: flex;
        align-items: center;
        margin-bottom: 20px;
        gap: 15px;
    }

    .battle-container .player-avatar {
        width: 60px;
        height: 60px;
        border-radius: 50%;
        background: linear-gradient(45deg, #667eea 0%, #764ba2 100%);
        display: flex;
        align-items: center;
        justify-content: center;
        font-size: 24px;
        color: white;
        box-shadow: 0 8px 16px rgba(0, 0, 0, 0.3);
        animation: pulse 2s infinite;
    }

    .battle-container .player-left .player-avatar {
        background: linear-gradient(45deg, #dc3545 0%, #c82333 100%);
    }

    .battle-container .player-right .player-avatar {
        background: linear-gradient(45deg, #007bff 0%, #0056b3 100%);
    }

    .battle-container .player-name {
        color: white;
        font-weight: bold;
        margin: 0;
        text-shadow: 2px 2px 4px rgba(0, 0, 0, 0.5);
        font-size: 1.5rem;
    }

    .winner-name {
        color: #ffd700 !important;
        text-shadow: 0 0 10px rgba(255, 215, 0, 0.8), 2px 2px 4px rgba(0, 0, 0, 0.5) !important;
        animation: nameGlow 1.5s ease-in-out infinite;
    }

    @keyframes nameGlow {
        0%,
        100% {
            text-shadow: 0 0 10px rgba(255, 215, 0, 0.8), 2px 2px 4px rgba(0, 0, 0, 0.5);
        }
        50% {
            text-shadow: 0 0 20px rgba(255, 215, 0, 1), 2px 2px 4px rgba(0, 0, 0, 0.5);
        }
    }

    .player-badge {
        padding: 4px 12px;
        border-radius: 20px;
        font-size: 0.75rem;
        font-weight: bold;
        text-transform: uppercase;
        letter-spacing: 1px;
        display: inline-block;
        width: 160px;
        text-align: center;
    }

    .player-badge.blue {
        background: linear-gradient(45deg, #007bff, #0056b3);
        color: white;
        box-shadow: 0 4px 8px rgba(0, 123, 255, 0.3);
    }

    .player-badge.red {
        background: linear-gradient(45deg, #dc3545, #c82333);
        color: white;
        box-shadow: 0 0 10px rgba(220, 53, 69, 0.3);
    }

    .winner-badge {
        background: linear-gradient(45deg, #ffd700, #ffed4e) !important;
        color: #000 !important;
        box-shadow: 0 0 15px rgba(255, 215, 0, 0.6) !important;
        font-weight: bold !important;
        animation: badgeGlow 1.5s ease-in-out infinite;
    }

    @keyframes badgeGlow {
        0%,
        100% {
            box-shadow: 0 0 15px rgba(255, 215, 0, 0.6);
        }
        50% {
            box-shadow: 0 0 25px rgba(255, 215, 0, 0.9);
        }
    }

    .player-stats {
        display: flex;
        flex-direction: column;
        gap: 12px;
    }

    .stat-item {
        display: flex;
        justify-content: space-between;
        align-items: center;
        padding: 8px 0;
        border-bottom: 1px solid rgba(255, 255, 255, 0.1);
    }

    /* 右侧玩家头像区域 - 头像在最右侧，信息在左侧 */
    .player-header-right {
        display: flex;
        flex-direction: row-reverse;
        align-items: center;
        gap: 15px;
    }

    /* 右侧玩家信息区域 - 文字右对齐 */
    .player-info-right {
        text-align: right;
        flex: 1;
    }

    /* 右侧统计项目 - 标签在右侧，内容在左侧 */
    .stat-item-right {
        display: flex;
        flex-direction: row-reverse;
        justify-content: space-between;
        align-items: center;
        text-align: right;
    }

    .stat-item-right .stat-label {
        text-align: right;
        margin-left: 10px;
        margin-right: 0;
    }

    .stat-item-right .stat-value {
        text-align: left;
    }

    /* 右侧玩家统计区域 */
    .player-stats-right {
        display: flex;
        flex-direction: column;
        gap: 12px;
    }

    .stat-label {
        color: #adb5bd;
        font-size: 0.85rem;
        text-transform: uppercase;
        letter-spacing: 0.5px;
    }

    .stat-value {
        color: white;
        font-weight: 600;
    }

    .lang-badge {
        background: rgba(255, 255, 255, 0.2);
        padding: 2px 8px;
        border-radius: 12px;
        font-size: 0.8rem;
        color: #fff;
    }

    .score-item {
        border: none;
        margin-top: 10px;
        padding: 15px;
        background: rgba(255, 255, 255, 0.05);
        border-radius: 10px;
    }

    .score-value {
        font-size: 2rem;
        font-weight: bold;
        text-shadow: 2px 2px 4px rgba(0, 0, 0, 0.5);
    }

    .score-value.blue {
        color: #007bff;
        text-shadow: 0 0 20px rgba(0, 123, 255, 0.5);
    }

    .score-value.red {
        color: #dc3545;
        text-shadow: 0 0 20px rgba(220, 53, 69, 0.5);
    }

    /* VS区域 - 增强版 */
    .vs-section-enhanced {
        position: relative;
        z-index: 10;
        display: flex;
        flex-direction: column;
        align-items: center;
        gap: 8px;
    }

    /* 战斗类型区域 */
    .battle-type-section {
        margin-bottom: 16px;
        display: flex;
        flex-direction: column;
        align-items: center;
        gap: 8px;
    }

    .battle-type-display {
        margin-bottom: 32px;
        padding: 12px 16px;
        border-radius: 15px;
        font-size: 1rem;
        font-weight: 700;
        display: inline-flex;
        align-items: center;
        gap: 8px;
        text-align: center;
        backdrop-filter: blur(5px);
        border: 1px solid rgba(255, 255, 255, 0.2);
        background: linear-gradient(45deg, rgba(100, 150, 255, 0.4), rgba(0, 212, 255, 0.3));
        color: rgba(255, 255, 255, 0.95);
        box-shadow: 0 0 15px rgba(100, 150, 255, 0.4);
        text-transform: uppercase;
        letter-spacing: 0.5px;
    }

    .map-display {
        padding: 2px 6px;
        border-radius: 8px;
        font-size: 0.8rem;
        font-weight: 500;
        display: inline-flex;
        align-items: center;
        gap: 3px;
        text-align: center;
        color: rgba(255, 255, 255, 0.8);
        background: rgba(255, 255, 255, 0.1);
        border: 1px solid rgba(255, 255, 255, 0.15);
    }

    /* 对战状态指示器 */
    .battle-status-indicator {
        margin-bottom: 5px;
    }

    .status-badge {
        padding: 4px 8px;
        border-radius: 12px;
        font-size: 0.7rem;
        font-weight: bold;
        text-transform: uppercase;
        letter-spacing: 0.5px;
        display: inline-flex;
        align-items: center;
        gap: 4px;
        animation: statusPulse 2s ease-in-out infinite;
    }

    .status-pending {
        background: linear-gradient(45deg, #ffc107, #ff8f00);
        color: white;
        box-shadow: 0 0 15px rgba(255, 193, 7, 0.4);
    }

    .status-running {
        background: linear-gradient(45deg, #17a2b8, #007bff);
        color: white;
        box-shadow: 0 0 15px rgba(23, 162, 184, 0.4);
        animation: runningPulse 1s ease-in-out infinite;
    }

    .status-finished {
        background: linear-gradient(45deg, #28a745, #20c997);
        color: white;
        box-shadow: 0 0 15px rgba(40, 167, 69, 0.4);
    }

    .status-error {
        background: linear-gradient(45deg, #dc3545, #c82333);
        color: white;
        box-shadow: 0 0 15px rgba(220, 53, 69, 0.4);
        animation: errorBlink 0.8s ease-in-out infinite;
    }

    /* 主VS圆圈 - 增强版 */
    .vs-circle-enhanced {
        width: 100px;
        height: 100px;
        border-radius: 50%;
        background: linear-gradient(45deg, #ff6b6b, #feca57, #48cae4, #f72585);
        background-size: 400% 400%;
        display: flex;
        flex-direction: column;
        align-items: center;
        justify-content: center;
        box-shadow: 0 0 40px rgba(255, 107, 107, 0.6);
        animation: gradientRotate 3s ease-in-out infinite, float 2s ease-in-out infinite;
        position: relative;
        margin: 10px 0;
    }

    .vs-circle-enhanced::before {
        content: '';
        position: absolute;
        width: 120px;
        height: 120px;
        border-radius: 50%;
        border: 2px solid rgba(255, 255, 255, 0.3);
        animation: pulse 2s ease-in-out infinite;
    }

    .vs-circle-enhanced::after {
        content: '';
        position: absolute;
        width: 140px;
        height: 140px;
        border-radius: 50%;
        border: 1px solid rgba(255, 255, 255, 0.1);
        animation: pulse 2s ease-in-out infinite reverse;
    }

    .vs-inner {
        display: flex;
        flex-direction: column;
        align-items: center;
        z-index: 2;
    }

    .vs-text {
        font-size: 1.5rem;
        font-weight: bold;
        color: white;
        text-shadow: 2px 2px 4px rgba(0, 0, 0, 0.7);
        margin-bottom: 2px;
    }

    .battle-id {
        font-size: 1.5rem;
        color: rgba(255, 255, 255, 0.8);
        font-weight: 600;
        text-shadow: 1px 1px 2px rgba(0, 0, 0, 0.5);
    }

    /* 对战结果显示 */
    .battle-result {
        margin-top: 10px;
    }

    .winner-indicator {
        padding: 4px 8px;
        border-radius: 10px;
        font-size: 1rem;
        font-weight: bold;
        display: inline-flex;
        align-items: center;
        gap: 4px;
        text-shadow: 1px 1px 2px rgba(0, 0, 0, 0.5);
    }

    .left-win {
        background: linear-gradient(45deg, #dc3545, #c82333);
        color: white;
        box-shadow: 0 0 15px rgba(220, 53, 69, 0.4);
        animation: victoryGlow 1.5s ease-in-out infinite;
    }

    .right-win {
        background: linear-gradient(45deg, #007bff, #0056b3);
        color: white;
        box-shadow: 0 0 15px rgba(0, 123, 255, 0.4);
        animation: victoryGlow 1.5s ease-in-out infinite;
    }

    .draw {
        background: linear-gradient(45deg, #ffc107, #ff8f00);
        color: white;
        box-shadow: 0 0 15px rgba(255, 193, 7, 0.4);
    }

    /* 对战时间信息 */
    .battle-time-info {
        display: flex;
        flex-direction: column;
        align-items: center;
        gap: 3px;
        margin-top: 24px;
    }

    .duration-display,
    .rounds-display {
        font-size: 0.8rem;
        color: rgba(255, 255, 255, 0.8);
        display: flex;
        align-items: center;
        gap: 3px;
        background: rgba(255, 255, 255, 0.1);
        padding: 2px 6px;
        border-radius: 8px;
        backdrop-filter: blur(5px);
    }

    /* 动态火花效果 - 增强版 */
    .battle-sparks-enhanced {
        position: absolute;
        width: 160px;
        height: 160px;
        top: 50%;
        left: 50%;
        transform: translate(-50%, -50%);
        pointer-events: none;
    }

    .battle-sparks-enhanced i {
        position: absolute;
        font-size: 14px;
        animation: sparkEnhanced 2s ease-in-out infinite;
    }

    .spark-1 {
        top: 5px;
        left: 50%;
        color: #ffd700;
        animation-delay: 0s;
    }

    .spark-2 {
        top: 50%;
        right: 5px;
        color: #ff6b6b;
        animation-delay: 0.4s;
    }

    .spark-3 {
        bottom: 5px;
        left: 5px;
        color: #48cae4;
        animation-delay: 0.8s;
    }

    .spark-4 {
        top: 20%;
        left: 20%;
        color: #f72585;
        animation-delay: 1.2s;
    }

    .spark-5 {
        bottom: 20%;
        right: 20%;
        color: #feca57;
        animation-delay: 1.6s;
    }

    /* 动画效果 - 增强版 */
    @keyframes pulse {
        0%,
        100% {
            transform: scale(1);
            opacity: 1;
        }

        50% {
            transform: scale(1.1);
            opacity: 0.7;
        }
    }

    @keyframes rotate {
        0% {
            transform: rotate(0deg);
        }

        100% {
            transform: rotate(360deg);
        }
    }

    @keyframes spark {
        0%,
        100% {
            opacity: 0;
            transform: scale(0.5);
        }

        50% {
            opacity: 1;
            transform: scale(1.2);
        }
    }

    /* 新增动画效果 */
    @keyframes statusPulse {
        0%,
        100% {
            transform: scale(1);
        }

        50% {
            transform: scale(1.05);
        }
    }

    @keyframes runningPulse {
        0%,
        100% {
            box-shadow: 0 0 15px rgba(23, 162, 184, 0.4);
        }

        50% {
            box-shadow: 0 0 25px rgba(23, 162, 184, 0.8);
        }
    }

    @keyframes errorBlink {
        0%,
        100% {
            opacity: 1;
        }

        50% {
            opacity: 0.7;
        }
    }

    @keyframes gradientRotate {
        0% {
            background-position: 0% 50%;
        }

        50% {
            background-position: 100% 50%;
        }

        100% {
            background-position: 0% 50%;
        }
    }

    @keyframes float {
        0%,
        100% {
            transform: translateY(0px);
        }

        50% {
            transform: translateY(-5px);
        }
    }

    @keyframes victoryGlow {
        0%,
        100% {
            transform: scale(1);
        }

        50% {
            transform: scale(1.1);
            box-shadow: 0 0 25px currentColor;
        }
    }

    @keyframes sparkEnhanced {
        0%,
        100% {
            opacity: 0;
            transform: scale(0.5) rotate(0deg);
        }

        25% {
            opacity: 0.7;
            transform: scale(1) rotate(90deg);
        }

        50% {
            opacity: 1;
            transform: scale(1.3) rotate(180deg);
        }

        75% {
            opacity: 0.7;
            transform: scale(1) rotate(270deg);
        }
    }

    /* 时间轴进度条样式 */
    .timeline-container {
        background: #f8f9fa;
        border-radius: 12px;
        padding: 20px;
        border: 1px solid #e9ecef;
    }

    .timeline-label {
        font-size: 0.8rem;
        color: #6c757d;
        font-weight: 500;
    }

    .timeline-wrapper {
        position: relative;
        padding: 10px 0;
    }

    .timeline-track {
        position: relative;
        height: 8px;
        background: #e9ecef;
        border-radius: 4px;
        cursor: pointer;
        transition: all 0.2s ease;
    }

    .timeline-track:hover {
        background: #dee2e6;
        transform: scaleY(1.2);
    }

    .timeline-progress {
        position: absolute;
        top: 0;
        left: 0;
        height: 100%;
        background: linear-gradient(90deg, #007bff, #0056b3);
        border-radius: 4px;
        transition: width 0.3s ease;
        box-shadow: 0 2px 4px rgba(0, 123, 255, 0.3);
    }

    .timeline-handle {
        position: absolute;
        top: 50%;
        width: 20px;
        height: 20px;
        background: #007bff;
        border: 3px solid #fff;
        border-radius: 50%;
        transform: translate(-50%, -50%);
        cursor: grab;
        transition: all 0.2s ease;
        box-shadow: 0 2px 8px rgba(0, 123, 255, 0.4);
        z-index: 10;
    }

    .timeline-handle:hover {
        transform: translate(-50%, -50%) scale(1.2);
        box-shadow: 0 4px 12px rgba(0, 123, 255, 0.6);
    }

    .timeline-handle:active {
        cursor: grabbing;
        transform: translate(-50%, -50%) scale(1.1);
    }

    .timeline-marker {
        position: absolute;
        top: 50%;
        width: 8px;
        height: 8px;
        border-radius: 50%;
        transform: translate(-50%, -50%);
        cursor: pointer;
        transition: all 0.2s ease;
        z-index: 5;
    }

    .timeline-marker.normal {
        background: #6c757d;
        border: 2px solid #fff;
    }

    .timeline-marker.important {
        background: #ffc107;
        border: 2px solid #fff;
        box-shadow: 0 0 8px rgba(255, 193, 7, 0.5);
    }

    .timeline-marker.critical {
        background: #dc3545;
        border: 2px solid #fff;
        box-shadow: 0 0 8px rgba(220, 53, 69, 0.5);
        animation: criticalPulse 2s ease-in-out infinite;
    }

    .timeline-marker:hover {
        transform: translate(-50%, -50%) scale(1.3);
    }

    .timeline-current-info {
        display: flex;
        align-items: center;
    }

    .timeline-controls button {
        color: #6c757d;
        transition: color 0.2s ease;
    }

    .timeline-controls button:hover {
        color: #007bff;
    }

    .timeline-controls button:disabled {
        color: #dee2e6;
        cursor: not-allowed;
    }

    /* 当前回合详情样式 */
    #current-round-container {
        min-height: 200px;
        transition: all 0.3s ease;
    }

    .round-detail-card {
        border: 1px solid #e9ecef;
        border-radius: 8px;
        overflow: hidden;
        transition: all 0.3s ease;
    }

    .round-detail-card:hover {
        box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
        transform: translateY(-2px);
    }

    .round-detail-header {
        background: linear-gradient(135deg, #f8f9fa, #e9ecef);
        padding: 12px 16px;
        border-bottom: 1px solid #e9ecef;
    }

    .round-detail-body {
        padding: 16px;
    }

    .player-actions-section {
        background: linear-gradient(135deg, rgba(100, 150, 255, 0.1), rgba(0, 212, 255, 0.05));
        border: 1px solid rgba(100, 150, 255, 0.3);
        border-radius: 12px;
        padding: 15px;
        margin-bottom: 15px;
        backdrop-filter: blur(10px);
        box-shadow: 0 4px 16px rgba(0, 0, 0, 0.1);
    }

    .action-item {
        background: rgba(255, 255, 255, 0.1);
        border: 1px solid rgba(100, 150, 255, 0.2);
        border-radius: 8px;
        padding: 12px;
        margin-bottom: 10px;
        transition: all 0.2s ease;
        backdrop-filter: blur(5px);
        color: rgba(255, 255, 255, 0.9);
    }

    .action-item:hover {
        background: rgba(255, 255, 255, 0.15);
        border-color: rgba(100, 150, 255, 0.4);
        transform: translateY(-1px);
        box-shadow: 0 4px 12px rgba(100, 150, 255, 0.2);
    }

    /* 在现有的action-item样式后添加 */
    .action-item.success {
        border-color: rgba(40, 167, 69, 0.4);
        background: rgba(40, 167, 69, 0.1);
        color: rgba(72, 187, 120, 0.9);
    }

    .action-item.success:hover {
        border-color: rgba(40, 167, 69, 0.6);
        background: rgba(40, 167, 69, 0.15);
        box-shadow: 0 4px 12px rgba(40, 167, 69, 0.2);
    }

    .action-item.failed {
        border-color: rgba(220, 53, 69, 0.4);
        background: rgba(220, 53, 69, 0.1);
        color: rgba(248, 113, 113, 0.9);
    }

    .action-item.failed:hover {
        border-color: rgba(220, 53, 69, 0.6);
        background: rgba(220, 53, 69, 0.15);
        box-shadow: 0 4px 12px rgba(220, 53, 69, 0.2);
    }

    .action-item code {
        color: inherit;
        background: transparent;
    }

    .action-item.success code {
        color: rgba(72, 187, 120, 0.9);
    }

    .action-item.failed code {
        color: rgba(248, 113, 113, 0.9);
    }

    /* 命令执行详情样式 */
    .command-info {
        margin-bottom: 8px;
        font-weight: 500;
    }

    .entity-state {
        font-size: 0.85rem;
        color: rgba(255, 255, 255, 0.8);
        background: rgba(100, 150, 255, 0.1);
        border-radius: 4px;
        padding: 4px 8px;
        margin: 2px 0;
        border-left: 3px solid rgba(100, 150, 255, 0.5);
    }

    .entity-state strong {
        color: rgba(100, 150, 255, 0.9);
    }

    .error-info {
        font-size: 0.85rem;
        background: rgba(220, 53, 69, 0.12);
        border-radius: 6px;
        padding: 8px 12px;
        margin-top: 6px;
        border-left: 3px solid rgba(220, 53, 69, 0.6);
        border: 1px solid rgba(220, 53, 69, 0.2);
        box-shadow: 0 2px 4px rgba(220, 53, 69, 0.1);
        transition: all 0.2s ease;
    }

    .error-info:hover {
        background: rgba(220, 53, 69, 0.18);
        border-color: rgba(220, 53, 69, 0.3);
        box-shadow: 0 3px 6px rgba(220, 53, 69, 0.15);
    }

    .error-info strong {
        color: rgba(248, 113, 113, 1);
        font-weight: 600;
    }

    /* 错误堆栈信息样式 */
    .error-stack {
        margin-top: 8px;
    }

    .error-stack summary {
        outline: none;
        user-select: none;
        padding: 4px 8px;
        border-radius: 4px;
        background-color: rgba(255, 193, 7, 0.1);
        border: 1px solid rgba(255, 193, 7, 0.3);
        transition: all 0.2s ease;
        font-size: 0.8rem;
    }

    .error-stack summary:hover {
        background-color: rgba(255, 193, 7, 0.2);
        border-color: rgba(255, 193, 7, 0.5);
    }

    .error-stack-content {
        background-color: rgba(42, 43, 44, 0.9);
        border: 1px solid rgb(252, 58, 24);
        border-radius: 4px;
        padding: 12px;
        margin-top: 8px;
        font-family: 'Courier New', monospace;
        font-size: 0.75rem;
        line-height: 1.4;
        color: rgb(201, 204, 202);
        white-space: pre-wrap;
        word-break: break-word;
        max-height: 300px;
        overflow-y: auto;
        backdrop-filter: blur(5px);
    }

    /* 隐藏undefined错误的样式 */
    .action-item.undefined-error {
        display: none !important;
    }

    /* 简化的区间选择器样式 */
    .simple-range-selector {
        background: linear-gradient(135deg, rgba(100, 150, 255, 0.1), rgba(0, 212, 255, 0.05));
        border: 1px solid rgba(100, 150, 255, 0.4);
        border-radius: 15px;
        padding: 25px;
        backdrop-filter: blur(15px);
        box-shadow: 0 8px 32px rgba(100, 150, 255, 0.1);
        transition: all 0.3s ease;
    }

    .simple-range-selector:hover {
        border-color: rgba(100, 150, 255, 0.6);
        box-shadow: 0 12px 40px rgba(100, 150, 255, 0.15);
    }

    .simple-range-selector h5,
    .simple-range-selector h6 {
        color: rgba(255, 255, 255, 0.95) !important;
        font-weight: 600;
        margin-bottom: 20px;
        text-shadow: 0 2px 4px rgba(0, 0, 0, 0.3);
    }

    .simple-range-selector label,
    .simple-range-selector .form-label {
        color: rgba(255, 255, 255, 0.85) !important;
        font-weight: 500;
        font-size: 0.9rem;
        text-shadow: 0 1px 2px rgba(0, 0, 0, 0.2);
    }

    .simple-range-selector .text-muted,
    .simple-range-selector small {
        color: rgba(255, 255, 255, 0.6) !important;
    }

    .simple-range-selector .badge {
        background: linear-gradient(135deg, rgba(100, 150, 255, 0.3), rgba(0, 212, 255, 0.2)) !important;
        border: 1px solid rgba(100, 150, 255, 0.4);
        color: rgba(255, 255, 255, 0.9) !important;
        backdrop-filter: blur(3px);
    }

    .simple-range-selector input[type='number'],
    .simple-range-selector .form-control {
        background: rgba(255, 255, 255, 0.1) !important;
        border: 1px solid rgba(100, 150, 255, 0.3) !important;
        border-radius: 8px !important;
        color: rgba(255, 255, 255, 0.9) !important;
        padding: 8px 12px !important;
        backdrop-filter: blur(5px);
        transition: all 0.2s ease !important;
    }

    .simple-range-selector input[type='number']:focus,
    .simple-range-selector .form-control:focus {
        outline: none !important;
        border-color: rgba(100, 150, 255, 0.6) !important;
        box-shadow: 0 0 0 3px rgba(100, 150, 255, 0.2) !important;
        background: rgba(255, 255, 255, 0.15) !important;
    }

    .simple-range-selector .form-control::placeholder {
        color: rgba(255, 255, 255, 0.5) !important;
    }

    .simple-range-selector .form-select,
    .simple-range-selector select {
        background: rgba(255, 255, 255, 0.1) !important;
        border: 1px solid rgba(100, 150, 255, 0.3) !important;
        border-radius: 8px !important;
        color: rgba(255, 255, 255, 0.9) !important;
        padding: 8px 12px !important;
        backdrop-filter: blur(5px);
        transition: all 0.2s ease !important;
    }

    .simple-range-selector .form-select:focus,
    .simple-range-selector select:focus {
        outline: none !important;
        border-color: rgba(100, 150, 255, 0.6) !important;
        box-shadow: 0 0 0 3px rgba(100, 150, 255, 0.2) !important;
        background: rgba(255, 255, 255, 0.15) !important;
    }

    .simple-range-selector .form-select option,
    .simple-range-selector select option {
        background: #1a1a2e !important;
        color: rgba(255, 255, 255, 0.9) !important;
    }

    /* 修复搜索和过滤区域的样式 */
    #command-type-filter,
    #round-filter {
        background: rgba(255, 255, 255, 0.1) !important;
        border: 1px solid rgba(100, 150, 255, 0.3) !important;
        border-radius: 8px !important;
        color: rgba(255, 255, 255, 0.9) !important;
        backdrop-filter: blur(5px);
    }

    #command-type-filter:focus,
    #round-filter:focus {
        outline: none !important;
        border-color: rgba(100, 150, 255, 0.6) !important;
        box-shadow: 0 0 0 3px rgba(100, 150, 255, 0.2) !important;
        background: rgba(255, 255, 255, 0.15) !important;
    }

    #command-type-filter option,
    #round-filter option {
        background: #1a1a2e !important;
        color: rgba(255, 255, 255, 0.9) !important;
    }

    .simple-range-slider {
        position: relative;
        height: 50px;
        margin: 20px 0;
        padding: 10px 0;
    }

    .range-input {
        position: absolute;
        width: 100%;
        height: 8px;
        background: transparent;
        outline: none;
        appearance: none;
        -webkit-appearance: none;
        pointer-events: none;
    }

    .range-input::-webkit-slider-thumb {
        -webkit-appearance: none;
        appearance: none;
        width: 22px;
        height: 22px;
        border-radius: 50%;
        background: linear-gradient(135deg, #6496ff, #4a7fff);
        border: 3px solid rgba(255, 255, 255, 0.9);
        cursor: pointer;
        pointer-events: all;
        box-shadow: 0 4px 12px rgba(100, 150, 255, 0.4), 0 2px 6px rgba(0, 0, 0, 0.2);
        transition: all 0.2s ease;
    }

    .range-input::-webkit-slider-thumb:hover {
        transform: scale(1.1);
        box-shadow: 0 6px 16px rgba(100, 150, 255, 0.5), 0 3px 8px rgba(0, 0, 0, 0.3);
    }

    .range-input::-moz-range-thumb {
        width: 22px;
        height: 22px;
        border-radius: 50%;
        background: linear-gradient(135deg, #6496ff, #4a7fff);
        border: 3px solid rgba(255, 255, 255, 0.9);
        cursor: pointer;
        pointer-events: all;
        box-shadow: 0 4px 12px rgba(100, 150, 255, 0.4), 0 2px 6px rgba(0, 0, 0, 0.2);
        transition: all 0.2s ease;
    }

    .range-input.end::-webkit-slider-thumb {
        background: linear-gradient(135deg, #00d4ff, #00b8e6);
        box-shadow: 0 4px 12px rgba(0, 212, 255, 0.4), 0 2px 6px rgba(0, 0, 0, 0.2);
    }

    .range-input.end::-webkit-slider-thumb:hover {
        box-shadow: 0 6px 16px rgba(0, 212, 255, 0.5), 0 3px 8px rgba(0, 0, 0, 0.3);
    }

    .range-input.end::-moz-range-thumb {
        background: linear-gradient(135deg, #00d4ff, #00b8e6);
        box-shadow: 0 4px 12px rgba(0, 212, 255, 0.4), 0 2px 6px rgba(0, 0, 0, 0.2);
    }

    .range-track {
        position: absolute;
        top: 50%;
        left: 0;
        right: 0;
        height: 8px;
        background: rgba(255, 255, 255, 0.15);
        border-radius: 4px;
        transform: translateY(-50%);
        pointer-events: none;
        box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.2);
    }

    .range-fill {
        position: absolute;
        height: 100%;
        background: linear-gradient(90deg, #6496ff, #00d4ff);
        border-radius: 4px;
        transition: all 0.2s ease;
        box-shadow: 0 2px 8px rgba(100, 150, 255, 0.3);
    }

    .range-text {
        position: absolute;
        top: 50%;
        left: 50%;
        transform: translate(-50%, -50%);
        font-size: 0.9rem;
        font-weight: 600;
        color: rgba(255, 255, 255, 0.9);
        text-shadow: 0 1px 2px rgba(0, 0, 0, 0.3);
    }

    /* 游戏风格按钮样式 */
    .range-btn,
    .simple-range-selector .btn-primary,
    .simple-range-selector .btn {
        background: linear-gradient(135deg, #6496ff, #00d4ff) !important;
        border: 1px solid rgba(255, 255, 255, 0.2) !important;
        border-radius: 8px !important;
        padding: 10px 20px !important;
        font-weight: 600 !important;
        font-size: 0.9rem !important;
        text-transform: uppercase;
        letter-spacing: 0.5px;
        transition: all 0.3s ease !important;
        box-shadow: 0 4px 12px rgba(100, 150, 255, 0.3), 0 2px 6px rgba(0, 0, 0, 0.1) !important;
        color: rgba(255, 255, 255, 0.95) !important;
        text-shadow: 0 1px 2px rgba(0, 0, 0, 0.3);
        backdrop-filter: blur(5px);
        cursor: pointer;
        will-change: transform;
    }

    .range-btn:hover,
    .simple-range-selector .btn-primary:hover,
    .simple-range-selector .btn:hover {
        transform: translateY(-2px) !important;
        box-shadow: 0 6px 20px rgba(100, 150, 255, 0.4), 0 4px 12px rgba(0, 0, 0, 0.15) !important;
        border-color: rgba(255, 255, 255, 0.3) !important;
        background: linear-gradient(135deg, #7ba7ff, #1ae0ff) !important;
    }

    .range-btn:active,
    .simple-range-selector .btn-primary:active,
    .simple-range-selector .btn:active {
        transform: translateY(0) !important;
        box-shadow: 0 2px 8px rgba(100, 150, 255, 0.3), 0 1px 4px rgba(0, 0, 0, 0.1) !important;
    }

    .range-btn-reset,
    .simple-range-selector .btn-outline-secondary {
        background: linear-gradient(135deg, rgba(255, 255, 255, 0.1), rgba(255, 255, 255, 0.05)) !important;
        border: 1px solid rgba(255, 255, 255, 0.3) !important;
        color: rgba(255, 255, 255, 0.8) !important;
        box-shadow: 0 4px 12px rgba(255, 255, 255, 0.1), 0 2px 6px rgba(0, 0, 0, 0.1) !important;
    }

    .range-btn-reset:hover,
    .simple-range-selector .btn-outline-secondary:hover {
        background: linear-gradient(135deg, rgba(255, 255, 255, 0.15), rgba(255, 255, 255, 0.1)) !important;
        color: rgba(255, 255, 255, 0.9) !important;
        box-shadow: 0 6px 20px rgba(255, 255, 255, 0.15), 0 4px 12px rgba(0, 0, 0, 0.15) !important;
        border-color: rgba(255, 255, 255, 0.4) !important;
    }

    /* 游戏风格回合列表容器 */
    .range-rounds-container {
        background: linear-gradient(135deg, rgba(255, 255, 255, 0.05), rgba(100, 150, 255, 0.02));
        border-radius: 12px;
        padding: 20px;
        border: 1px solid rgba(100, 150, 255, 0.2);
        box-shadow: 0 4px 16px rgba(0, 0, 0, 0.1), 0 2px 8px rgba(100, 150, 255, 0.05);
        backdrop-filter: blur(10px);
        margin-top: 20px;
    }

    .range-rounds-header {
        border-bottom: 1px solid rgba(100, 150, 255, 0.3);
        padding-bottom: 15px;
        margin-bottom: 20px;
    }

    .range-rounds-header h6 {
        color: rgba(255, 255, 255, 0.95);
        font-weight: 600;
        font-size: 1.1rem;
        margin: 0;
        text-shadow: 0 2px 4px rgba(0, 0, 0, 0.3);
    }

    .range-summary {
        display: flex;
        align-items: center;
        gap: 12px;
        font-size: 0.9rem;
        color: rgba(255, 255, 255, 0.8);
        text-shadow: 0 1px 2px rgba(0, 0, 0, 0.2);
    }

    .round-item-compact {
        background: linear-gradient(135deg, rgba(255, 255, 255, 0.08), rgba(100, 150, 255, 0.03));
        border-radius: 8px;
        padding: 12px;
        margin-bottom: 8px;
        border-left: 3px solid #6496ff;
        border: 1px solid rgba(100, 150, 255, 0.2);
        transition: all 0.3s ease;
        cursor: pointer;
        backdrop-filter: blur(5px);
        color: rgba(255, 255, 255, 0.9);
    }

    .round-item-compact:hover {
        background: linear-gradient(135deg, rgba(255, 255, 255, 0.12), rgba(100, 150, 255, 0.08));
        transform: translateX(4px);
        box-shadow: 0 4px 12px rgba(100, 150, 255, 0.2), 0 2px 6px rgba(0, 0, 0, 0.1);
        border-left-color: #00d4ff;
        border-color: rgba(100, 150, 255, 0.4);
        color: rgba(255, 255, 255, 0.95);
    }

    .round-item-compact:last-child {
        margin-bottom: 0;
    }

    .round-item-header {
        display: flex;
        justify-content: space-between;
        align-items: center;
        margin-bottom: 8px;
        font-size: 0.85rem;
        color: rgba(255, 255, 255, 0.9);
        font-weight: 500;
    }

    .round-item-summary {
        display: flex;
        gap: 18px;
        font-size: 0.9rem;
        color: rgba(255, 255, 255, 0.75);
        text-shadow: 0 1px 2px rgba(0, 0, 0, 0.2);
    }

    .round-item-actions {
        display: flex;
        gap: 12px;
    }

    .action-count {
        display: flex;
        align-items: center;
        gap: 6px;
        color: rgba(255, 255, 255, 0.8);
    }

    .action-count .badge {
        font-size: 0.75rem;
        padding: 3px 8px;
        background: linear-gradient(135deg, rgba(100, 150, 255, 0.3), rgba(0, 212, 255, 0.2));
        border: 1px solid rgba(100, 150, 255, 0.4);
        color: rgba(255, 255, 255, 0.9);
        border-radius: 12px;
        backdrop-filter: blur(3px);
    }

    .action-item:hover {
        border-color: #007bff;
        box-shadow: 0 2px 4px rgba(0, 123, 255, 0.1);
    }

    .action-item:last-child {
        margin-bottom: 0;
    }

    /* 动画效果 */
    @keyframes criticalPulse {
        0%,
        100% {
            box-shadow: 0 0 8px rgba(220, 53, 69, 0.5);
        }

        50% {
            box-shadow: 0 0 16px rgba(220, 53, 69, 0.8);
        }
    }

    @keyframes slideInUp {
        from {
            opacity: 0;
            transform: translateY(20px);
        }

        to {
            opacity: 1;
            transform: translateY(0);
        }
    }

    .slide-in-up {
        animation: slideInUp 0.3s ease-out;
    }

    /* 响应式设计 */
    @media (max-width: 768px) {
        .timeline-container {
            padding: 15px;
        }

        .timeline-handle {
            width: 24px;
            height: 24px;
        }

        .timeline-marker {
            width: 10px;
            height: 10px;
        }

        .battle-arena {
            padding: 20px;
            /* 保持与桌面版一致的视觉效果 */
            background: linear-gradient(135deg, #1a1a2e 0%, #16213e 50%, #0f3460 100%);
            border-radius: 20px;
            box-shadow: 0 20px 40px rgba(0, 0, 0, 0.3);
            position: relative;
            overflow: hidden;
        }

        .battle-arena::before {
            content: '';
            position: absolute;
            top: 0;
            left: 0;
            right: 0;
            bottom: 0;
            background: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100"><defs><pattern id="grid" width="10" height="10" patternUnits="userSpaceOnUse"><path d="M 10 0 L 0 0 0 10" fill="none" stroke="%23ffffff" stroke-width="0.5" opacity="0.1"/></pattern></defs><rect width="100" height="100" fill="url(%23grid)"/></svg>');
            pointer-events: none;
        }

        .player-card {
            transform: none;
            margin-bottom: 20px;
        }

        .vs-section-enhanced {
            margin: 20px 0;
            gap: 6px;
        }

        .vs-circle-enhanced {
            width: 80px;
            height: 80px;
        }

        .vs-text {
            font-size: 1rem;
        }

        .battle-id {
            font-size: 0.55rem;
        }

        .battle-type-display {
            font-size: 0.7rem;
            padding: 6px 10px;
        }

        .map-display {
            font-size: 0.55rem;
            padding: 2px 6px;
        }

        .status-badge {
            font-size: 0.6rem;
            padding: 3px 6px;
        }

        .winner-indicator {
            font-size: 0.6rem;
            padding: 3px 6px;
        }

        .duration-display,
        .rounds-display {
            font-size: 0.6rem;
            padding: 1px 4px;
        }

        .battle-sparks-enhanced {
            width: 120px;
            height: 120px;
        }

        .battle-sparks-enhanced i {
            font-size: 12px;
        }

        .battle-container .player-name {
            font-size: 1.2rem;
        }

        .score-value {
            font-size: 1.5rem;
        }
    }

    /* 战斗统计样式 */
    .battle-stats {
        background: linear-gradient(135deg, rgba(255, 255, 255, 0.05), rgba(100, 150, 255, 0.02));
        border: 1px solid rgba(100, 150, 255, 0.2);
        border-radius: 12px;
        padding: 20px;
        margin: 20px 0;
        backdrop-filter: blur(10px);
        box-shadow: 0 4px 20px rgba(0, 0, 0, 0.1);
    }

    .battle-stats h4 {
        color: rgba(255, 255, 255, 0.95);
        font-weight: 600;
        margin-bottom: 20px;
        text-shadow: 0 2px 4px rgba(0, 0, 0, 0.3);
        display: flex;
        align-items: center;
        gap: 10px;
    }

    .battle-summary {
        display: grid;
        grid-template-columns: 1fr 1fr;
        gap: 20px;
        margin-bottom: 20px;
    }

    .stats-card {
        background: linear-gradient(135deg, rgba(255, 255, 255, 0.08), rgba(100, 150, 255, 0.03));
        border: 1px solid rgba(100, 150, 255, 0.2);
        border-radius: 8px;
        padding: 15px;
        backdrop-filter: blur(5px);
    }

    .stats-card h5 {
        color: rgba(255, 255, 255, 0.9);
        font-size: 1rem;
        margin-bottom: 10px;
        font-weight: 500;
    }

    .stat-row {
        display: flex;
        justify-content: space-between;
        align-items: center;
        margin-bottom: 8px;
        color: rgba(255, 255, 255, 0.8);
        font-size: 0.9rem;
    }

    .stat-row:last-child {
        margin-bottom: 0;
    }

    .stat-value {
        font-weight: 600;
        color: rgba(255, 255, 255, 0.95);
    }

    .stat-value.success {
        color: #28a745;
    }

    .stat-value.error {
        color: #dc3545;
    }

    .stat-value.rate {
        color: #17a2b8;
    }

    .execution-actions {
        display: flex;
        gap: 15px;
        margin-bottom: 20px;
    }

    .btn-execution {
        background: linear-gradient(135deg, rgba(100, 150, 255, 0.2), rgba(0, 212, 255, 0.1));
        border: 1px solid rgba(100, 150, 255, 0.4);
        color: rgba(255, 255, 255, 0.9);
        padding: 8px 16px;
        border-radius: 6px;
        font-size: 0.9rem;
        cursor: pointer;
        transition: all 0.3s ease;
        backdrop-filter: blur(5px);
    }

    .btn-execution:hover {
        background: linear-gradient(135deg, rgba(100, 150, 255, 0.3), rgba(0, 212, 255, 0.2));
        border-color: rgba(100, 150, 255, 0.6);
        color: rgba(255, 255, 255, 0.95);
        transform: translateY(-1px);
        box-shadow: 0 4px 12px rgba(100, 150, 255, 0.2);
    }

    .execution-details {
        display: none;
        margin-top: 20px;
    }

    .execution-details.show {
        display: block;
        animation: slideInUp 0.3s ease-out;
    }

    .failed-commands-list {
        max-height: 300px;
        overflow-y: auto;
        border: 1px solid rgba(100, 150, 255, 0.2);
        border-radius: 8px;
        background: rgba(0, 0, 0, 0.2);
    }

    .failed-command-item {
        padding: 12px;
        border-bottom: 1px solid rgba(100, 150, 255, 0.1);
        transition: background-color 0.2s ease;
    }

    .failed-command-item:last-child {
        border-bottom: none;
    }

    .failed-command-item:hover {
        background: rgba(100, 150, 255, 0.05);
    }

    .failed-command-text {
        font-family: 'Courier New', monospace;
        font-size: 0.85rem;
        color: rgba(255, 255, 255, 0.8);
        word-break: break-all;
        margin-bottom: 5px;
    }

    .failed-command-error {
        font-size: 0.8rem;
        color: #dc3545;
        font-style: italic;
    }

    /* 新增的JSON格式展示样式 */
    .failed-command-header {
        display: flex;
        justify-content: space-between;
        align-items: center;
        margin-bottom: 8px;
        padding-bottom: 5px;
        border-bottom: 1px solid rgba(100, 150, 255, 0.1);
    }

    .failed-command-content {
        margin-left: 10px;
    }

    .command-error {
        background: rgba(220, 53, 69, 0.1);
        border-left: 3px solid #dc3545;
        padding: 8px 12px;
        border-radius: 4px;
    }

    .error-message {
        color: #ff6b6b;
        font-weight: 500;
        margin-left: 8px;
    }

    .command-details {
        background: rgba(100, 150, 255, 0.05);
        border-left: 3px solid #6495ed;
        padding: 8px 12px;
        border-radius: 4px;
    }

    .json-display,
    .raw-display {
        background: rgba(0, 0, 0, 0.3);
        border: 1px solid rgba(100, 150, 255, 0.2);
        border-radius: 6px;
        padding: 12px;
        margin: 8px 0;
        overflow-x: auto;
        max-height: 300px;
        overflow-y: auto;
    }

    .json-display code,
    .raw-display code {
        font-family: 'Courier New', 'Monaco', 'Menlo', monospace;
        font-size: 0.85rem;
        color: rgba(255, 255, 255, 0.9);
        white-space: pre;
        line-height: 1.4;
    }

    .json-display {
        border-left: 3px solid #28a745;
    }

    .raw-display {
        border-left: 3px solid #ffc107;
    }

    .failed-command-time {
        font-size: 0.75rem;
        color: rgba(255, 255, 255, 0.6);
        text-align: right;
    }

    /* 响应式设计 */
    @media (max-width: 768px) {
        .battle-summary {
            grid-template-columns: 1fr;
            gap: 15px;
        }

        .execution-actions {
            flex-direction: column;
            gap: 10px;
        }

        .btn-execution {
            text-align: center;
        }

        .stats-card {
            padding: 12px;
        }

        .stat-row {
            font-size: 0.85rem;
        }
    }
</style>
<script>
    // 全局变量定义
    const battleData = JSON.parse(document.getElementById('battle-data').textContent);
    const battleId = battleData.id;

    // 简化的回放功能JavaScript代码
    (function () {
        'use strict';

        // 简化的区间选择器变量
        let roundsData = [];
        let totalRounds =  roundsData.length;

        // 全局变量用于分页
        let currentRoundsData = [];
        let currentDisplayedCount = 0;
        const ROUNDS_PER_PAGE = 10; // 每页显示的回合数

        // 回放相关变量
        let replayData = null;
        let battleBridge = null;
        let isReplayStarted = false;

        // 显示获胜信息
        function displayVictoryMessage() {
            const victorySection = document.getElementById('victory-message-section');
            const victoryText = document.getElementById('victory-message-text');

            if (!victorySection || !victoryText) {
                return;
            }

            try {
                // 从battle数据中获取end_command
                const battleElement = document.getElementById('battle-data');
                if (!battleElement) {
                    console.warn('未找到battle-data元素');
                    return;
                }

                const battle = JSON.parse(battleElement.textContent);

                // 检查是否有end_command和获胜信息
                if (battle.end_command &&
                    battle.end_command.param &&
                    battle.end_command.param.result &&
                    battle.end_command.param.result.msg) {

                    const victoryMessage = battle.end_command.param.result.msg;
                    victoryText.textContent = victoryMessage;
                    victorySection.style.display = 'block';

                    console.log('获胜信息已显示:', victoryMessage);
                } else {
                    console.log('未找到获胜信息，end_command结构:', battle.end_command);
                }
            } catch (error) {
                console.error('显示获胜信息时出错:', error);
            }
        }
        let isFullscreen = false;

        // 回放区域控制
        const btnStartReplay = document.getElementById('btn-start-replay');
        const btnFullscreen = document.getElementById('btn-fullscreen');
        const btnExitFullscreen = document.getElementById('btn-exit-fullscreen');
        const battleFrame = document.getElementById('battle-frame');

        // 开始回放按钮点击事件
        if (btnStartReplay) {
            btnStartReplay.addEventListener('click', function () {
                if (isReplayStarted) {
                    return;
                }
                startReplay();
            });
        }

        // 全屏按钮点击事件
        if (btnFullscreen) {
            btnFullscreen.addEventListener('click', function () {
                enterFullscreen();
            });
        }

        // 退出全屏按钮点击事件
        if (btnExitFullscreen) {
            btnExitFullscreen.addEventListener('click', function () {
                exitFullscreen();
            });
        }

        // 进入全屏
        function enterFullscreen() {
            const replayIframe = document.getElementById('replay-iframe');
            if (replayIframe && replayIframe.requestFullscreen) {
                replayIframe
                    .requestFullscreen()
                    .then(() => {
                        isFullscreen = true;
                        updateFullscreenButtons();
                    })
                    .catch((err) => {
                        console.error('进入全屏失败:', err);
                    });
            } else if (replayIframe && replayIframe.webkitRequestFullscreen) {
                // Safari 兼容性
                replayIframe.webkitRequestFullscreen();
                isFullscreen = true;
                updateFullscreenButtons();
            } else if (replayIframe && replayIframe.msRequestFullscreen) {
                // IE/Edge 兼容性
                replayIframe.msRequestFullscreen();
                isFullscreen = true;
                updateFullscreenButtons();
            } else {
                console.warn('浏览器不支持全屏API');
            }
        }

        // 退出全屏
        function exitFullscreen() {
            if (document.exitFullscreen) {
                document
                    .exitFullscreen()
                    .then(() => {
                        isFullscreen = false;
                        updateFullscreenButtons();
                    })
                    .catch((err) => {
                        console.error('退出全屏失败:', err);
                    });
            } else if (document.webkitExitFullscreen) {
                // Safari 兼容性
                document.webkitExitFullscreen();
                isFullscreen = false;
                updateFullscreenButtons();
            } else if (document.msExitFullscreen) {
                // IE/Edge 兼容性
                document.msExitFullscreen();
                isFullscreen = false;
                updateFullscreenButtons();
            }
        }

        // 更新全屏按钮状态
        function updateFullscreenButtons() {
            if (isFullscreen) {
                if (btnFullscreen) btnFullscreen.style.display = 'none';
                if (btnExitFullscreen) btnExitFullscreen.style.display = 'inline-block';
            } else {
                if (btnFullscreen) btnFullscreen.style.display = 'inline-block';
                if (btnExitFullscreen) btnExitFullscreen.style.display = 'none';
            }
        }

        // 初始化BattleBridge
        function initBattleBridge() {
            if (typeof BattleBridge !== 'undefined') {
                battleBridge = new BattleBridge();
                const replayIframe = document.getElementById('replay-iframe');
                if (replayIframe) {
                    battleBridge.init(replayIframe, function (message, type) {
                        console.log(`[${type.toUpperCase()}] ${message}`);
                    });
                }
                // 将battleBridge暴露给全局，供cocos访问
                window.battleBridge = battleBridge;
                console.log('BattleBridge已初始化并暴露到全局window对象');
            } else {
                console.error('BattleBridge未定义');
            }
        }

        // 加载回放数据
        function loadReplayData() {
            try {
                // 检查是否有异步加载的回合数据
                if (!roundsData || roundsData.length === 0) {
                    console.warn('回合数据尚未异步加载完成，无法生成回放数据');
                    return false;
                }

                const battleElement = document.getElementById('battle-data');
                if (!battleElement) {
                    console.error('无法找到对战数据元素');
                    return false;
                }

                const battle = JSON.parse(battleElement.textContent);

                let allActions = [];

                // init_command
                console.info('init_command:', battle.init_command);
                if (battle.init_command) {
                    allActions.push(battle.init_command);
                }

                // 使用异步加载的回合数据
                roundsData.forEach(round => {
                    if (round.player1_actions && Array.isArray(round.player1_actions)) {
                        allActions = allActions.concat(round.player1_actions);
                    }
                    if (round.player2_actions && Array.isArray(round.player2_actions)) {
                        allActions = allActions.concat(round.player2_actions);
                    }
                });

                // end_command
                console.info('end_command:', battle.end_command);
                if (battle.end_command) {
                    allActions.push(battle.end_command);
                }

                replayData = {
                    battle_id: battleId,
                    player1: {
                        username: battle.player1.username,
                        language: battle.player1_code.language,
                    },
                    player2: {
                        username: battle.player2.username,
                        language: battle.player2_code.language,
                    },
                    rounds: allActions,
                };

                console.log('回放数据已加载:', replayData);
                return true;
            } catch (e) {
                console.error('加载回放数据失败:', e);
                return false;
            }
        }

        // 开始回放
        function startReplay() {
            // 检查回放数据是否准备就绪
            if (!replayData) {
                // 如果回放数据未准备好，尝试重新加载
                const replayLoaded = loadReplayData();
                if (!replayLoaded) {
                    console.error('回放数据未准备就绪，无法开始回放');
                    alert('回放数据尚未加载完成，请稍后再试');
                    return;
                }
            }

            if (!battleBridge) {
                console.error('BattleBridge未准备就绪');
                alert('游戏引擎尚未初始化完成，请稍后再试');
                return;
            }

            isReplayStarted = true;
            btnStartReplay.disabled = true;
            btnStartReplay.innerHTML = '<i class="fas fa-spinner fa-spin"></i> 回放进行中...';

            // 发送完整的回放数据给Cocos处理
            const replayCommand = {
                type: 'start_replay',
                battle_id: replayData.battle_id,
                player1: replayData.player1,
                player2: replayData.player2,
                rounds: replayData.rounds,
                mode: 'replay',
            };

            // 等待iframe准备就绪后发送数据
            if (battleBridge.iframeReady) {
                battleBridge.sendCommand(replayCommand);
                console.log('回放数据已发送给Cocos');
            } else {
                console.warn('iframe未准备就绪，无法发送回放数据');
                alert('游戏画面尚未加载完成，请稍后再试');
            }
        }

        // 异步加载回合数据
        async function loadRoundsData() {
            try {
                console.log('开始异步加载回合数据...');
                const response = await fetch(`/battles/api/${battleId}/rounds/`);
                if (!response.ok) {
                    throw new Error(`HTTP error! status: ${response.status}`);
                }
                const data = await response.json();
                if (data.status === 'success') {
                    roundsData = data.data;
                    totalRounds = roundsData.length;
                    console.log('回合数据异步加载完成:', totalRounds, '回合');

                    // 更新页面显示
                    updateRangeDisplay();
                    updateRangeFill();

                    // 更新回合计数显示
                    updateRoundsCountDisplay();

                    // 加载回放数据
                    const replayLoaded = loadReplayData();
                    if (replayLoaded) {
                        console.log('回放数据已准备就绪');
                    } else {
                        console.warn('回放数据加载失败');
                    }

                    // 加载执行统计数据（仅在战斗完成时）
                    if ('{{ battle.status }}' === 'finished') {
                        loadExecutionStats(roundsData);
                        console.log('执行统计数据加载完成');
                    }

                    // 直接显示已加载的回合数据，避免重复请求
                    const startInput = document.getElementById('start-round');
                    const endInput = document.getElementById('end-round');
                    if (startInput && endInput) {
                        const startRound = parseInt(startInput.value) || 1;
                        const endRound = parseInt(endInput.value) || totalRounds;

                        // 从已加载的数据中筛选区间数据
                        const rangeData = roundsData.slice(startRound - 1, endRound);
                        displayRangeRoundsData(rangeData, battleData);
                        console.log(`使用已加载数据显示区间: ${startRound} - ${endRound}, 共 ${rangeData.length} 个回合`);
                    }

                    // 显示加载完成状态
                    const loadingIndicator = document.getElementById('rounds-loading');
                    if (loadingIndicator) {
                        loadingIndicator.style.display = 'none';
                    }

                    return true;
                } else {
                    throw new Error(data.error || '加载回合数据失败');
                }
            } catch (error) {
                console.error('异步加载回合数据失败:', error);
                const loadingIndicator = document.getElementById('rounds-loading');
                if (loadingIndicator) {
                    loadingIndicator.innerHTML = '<div class="alert alert-danger">加载回合数据失败，请刷新页面重试</div>';
                }
                return false;
            }
        }

        // 初始化简化的区间选择器
        async function initSimpleRangeSelector() {
            try {
                // 先尝试异步加载回合数据
                const loaded = await loadRoundsData();
                if (!loaded) {
                    return;
                }

                // 初始化滑块事件
                setupSimpleRangeEvents();

                // 更新初始显示
                updateRangeDisplay();
                updateRangeFill();

            } catch (e) {
                console.error('初始化区间选择器失败:', e);
            }
        }

        // 设置简化的区间选择器事件
        function setupSimpleRangeEvents() {
            const startSlider = document.getElementById('start-slider');
            const endSlider = document.getElementById('end-slider');
            const startInput = document.getElementById('start-round');
            const endInput = document.getElementById('end-round');
            const applyBtn = document.getElementById('apply-range');
            const resetBtn = document.getElementById('reset-range');

            // 滑块事件
            if (startSlider) {
                startSlider.addEventListener('input', function () {
                    const startVal = parseInt(this.value);
                    const endVal = parseInt(endSlider.value);

                    if (startVal > endVal) {
                        endSlider.value = startVal;
                        endInput.value = startVal;
                    }

                    startInput.value = startVal;
                    updateRangeDisplay();
                    updateRangeFill();
                });
            }

            if (endSlider) {
                endSlider.addEventListener('input', function () {
                    const startVal = parseInt(startSlider.value);
                    const endVal = parseInt(this.value);

                    if (endVal < startVal) {
                        startSlider.value = endVal;
                        startInput.value = endVal;
                    }

                    endInput.value = endVal;
                    updateRangeDisplay();
                    updateRangeFill();
                });
            }

            // 输入框事件
            if (startInput) {
                startInput.addEventListener('change', function () {
                    const val = Math.max(1, Math.min(totalRounds, parseInt(this.value) || 1));
                    this.value = val;
                    startSlider.value = val;

                    if (val > parseInt(endInput.value)) {
                        endInput.value = val;
                        endSlider.value = val;
                    }

                    if (val < parseInt(startInput.value)) {
                        startInput.value = val;
                        startSlider.value = val;
                    }

                    updateRangeDisplay();
                    updateRangeFill();
                });
            }

            // 按钮事件
            if (applyBtn) {
                applyBtn.addEventListener('click', function () {
                    const start = parseInt(startInput.value);
                    const end = parseInt(endInput.value);
                    console.log(`应用区间: ${start} - ${end}`);
                    loadRangeRoundsData(start, end);
                });
            }

            if (resetBtn) {
                resetBtn.addEventListener('click', function () {
                    startInput.value = 1;
                    endInput.value = totalRounds;
                    startSlider.value = 1;
                    endSlider.value = totalRounds;
                    updateRangeDisplay();
                    updateRangeFill();
                });
            }

            if (endInput) {
                endInput.addEventListener('change', function () {
                    const val = Math.max(1, Math.min(totalRounds, parseInt(this.value) || totalRounds));
                    this.value = val;
                    endSlider.value = val;

                    if (val < parseInt(startInput.value)) {
                        startInput.value = val;
                        startSlider.value = val;
                    }

                    updateRangeDisplay();
                    updateRangeFill();
                });
            }
        }

        // 更新区间填充条
        function updateRangeFill() {
            const startSlider = document.getElementById('start-slider');
            const endSlider = document.getElementById('end-slider');
            const rangeFill = document.getElementById('range-fill');

            if (startSlider && endSlider && rangeFill) {
                const start = parseInt(startSlider.value);
                const end = parseInt(endSlider.value);
                const max = parseInt(startSlider.max);

                const startPercent = ((start - 1) / (max - 1)) * 100;
                const endPercent = ((end - 1) / (max - 1)) * 100;

                rangeFill.style.left = startPercent + '%';
                rangeFill.style.width = (endPercent - startPercent) + '%';
            }
        }

        // 初始化回合筛选器
        function initRoundFilter() {
            const roundFilter = document.getElementById('round-filter');
            if (roundFilter) {
                roundFilter.addEventListener('change', function() {
                    const filterValue = this.value;
                    applyRoundFilter(filterValue);
                });
            }
        }

        // 初始化命令类型筛选器
        function initCommandTypeFilter() {
            const commandTypeFilter = document.getElementById('command-type-filter');
            if (commandTypeFilter) {
                commandTypeFilter.addEventListener('change', function() {
                    const filterValue = this.value;
                    applyCommandTypeFilter(filterValue);
                });
            }
        }

        // 应用回合筛选
        function applyRoundFilter(filterValue) {
            const startInput = document.getElementById('start-round');
            const endInput = document.getElementById('end-round');
            const commandTypeFilter = document.getElementById('command-type-filter');

            if (!startInput || !endInput) {
                return;
            }

            const startRound = parseInt(startInput.value) || 1;
            const endRound = parseInt(endInput.value) || totalRounds;
            const commandType = commandTypeFilter ? commandTypeFilter.value : 'all';

            // 根据筛选条件加载数据
            loadRangeRoundsDataWithFilter(startRound, endRound, filterValue, commandType);
        }

        // 应用命令类型筛选
        function applyCommandTypeFilter(commandType) {
            const startInput = document.getElementById('start-round');
            const endInput = document.getElementById('end-round');
            const roundFilter = document.getElementById('round-filter');

            if (!startInput || !endInput) {
                return;
            }

            const startRound = parseInt(startInput.value) || 1;
            const endRound = parseInt(endInput.value) || totalRounds;
            const roundFilterValue = roundFilter ? roundFilter.value : '';

            // 根据筛选条件加载数据
            loadRangeRoundsDataWithFilter(startRound, endRound, roundFilterValue, commandType);
        }

        // 带筛选条件的回合数据加载（使用已加载的数据，避免重复请求）
        function loadRangeRoundsDataWithFilter(startRound, endRound, filterValue, commandType = 'all') {
            const rangeRoundsList = document.getElementById('range-rounds-list');

            // 检查是否已有回合数据
            if (!roundsData || roundsData.length === 0) {
                rangeRoundsList.innerHTML = `
                    <div class="alert alert-warning">
                        <i class="fas fa-exclamation-triangle"></i> 回合数据尚未加载完成，请稍后重试
                    </div>
                `;
                return;
            }

            try {
                // 从已加载的数据中筛选区间数据
                let rangeData = roundsData.slice(startRound - 1, endRound);

                // 应用回合筛选条件（如果有）
                if (filterValue && filterValue.trim() !== '') {
                    rangeData = rangeData.filter(round => {
                        return applyRoundFilterLogic(round, filterValue);
                    });
                }

                // 应用命令类型筛选条件
                if (commandType && commandType !== 'all') {
                    rangeData = rangeData.filter(round => {
                        return applyCommandTypeFilterLogic(round, commandType);
                    });
                }

                // 显示筛选后的数据
                displayRangeRoundsData(rangeData, battleData);
                console.log(`使用已加载数据显示区间: ${startRound} - ${endRound}, 回合筛选: "${filterValue}", 命令类型筛选: "${commandType}", 共 ${rangeData.length} 个回合`);

            } catch (error) {
                console.error('筛选回合数据时出错:', error);
                rangeRoundsList.innerHTML = `
                    <div class="alert alert-danger">
                        <i class="fas fa-exclamation-triangle"></i> 筛选数据时出错: ${error.message}
                    </div>
                `;
                // 更新摘要文本为错误状态
                const rangeSummaryText = document.getElementById('range-summary-text');
                if (rangeSummaryText) {
                    rangeSummaryText.textContent = '处理错误';
                }
            }
        }

        // 命令类型筛选逻辑
        function applyCommandTypeFilterLogic(round, commandType) {
            if (!round) {
                return false;
            }

            // 检查玩家1的命令执行详情
            if (round.player1_command_execution_details && Array.isArray(round.player1_command_execution_details)) {
                for (const detail of round.player1_command_execution_details) {
                    if (detail && detail.command && detail.command.type === commandType) {
                        return true;
                    }
                }
            }

            // 检查玩家2的命令执行详情
            if (round.player2_command_execution_details && Array.isArray(round.player2_command_execution_details)) {
                for (const detail of round.player2_command_execution_details) {
                    if (detail && detail.command && detail.command.type === commandType) {
                        return true;
                    }
                }
            }

            return false;
        }

        // 应用回合筛选逻辑（对应Python后端的筛选逻辑）
        function applyRoundFilterLogic(round, filterType) {
            if (!filterType || filterType.trim() === '') {
                return true; // 无筛选条件，显示所有回合
            }

            switch (filterType) {
                case 'error-or-failed':
                    // 筛选有错误或失败命令的回合（对应Python的Q(player1_failed_commands__gt=0) | Q(player2_failed_commands__gt=0) | ...）
                    return (round.player1_failed_commands > 0) ||
                           (round.player2_failed_commands > 0) ||
                           hasFailedCommandInDetails(round.player1_command_execution_details) ||
                           hasFailedCommandInDetails(round.player2_command_execution_details);

                case 'player1-error-or-failed':
                    // 筛选玩家1有错误或失败命令的回合
                    return (round.player1_failed_commands > 0) ||
                           hasFailedCommandInDetails(round.player1_command_execution_details);

                case 'player2-error-or-failed':
                    // 筛选玩家2有错误或失败命令的回合
                    return (round.player2_failed_commands > 0) ||
                           hasFailedCommandInDetails(round.player2_command_execution_details);

                default:
                    return true; // 未知筛选类型，显示所有回合
            }
        }

        // 检查命令执行详情中是否包含代码执行异常（区分代码异常和普通命令失败）
        function hasCodeExecutionExceptionInDetails(commandExecutionDetails) {
            if (!commandExecutionDetails) {
                return false;
            }

            // 定义代码异常类型（与battle_engine.py中的CodeExecutionErrorTypes对应）
            const codeExceptionTypes = [
                'timeout', 'syntax_error', 'runtime_error', 'output_format_error',
                'command_format_error', 'compilation_error', 'import_error',
                'memory_error', 'permission_error', 'execution_exception', 'unknown_error'
            ];

            try {
                // 如果是字符串，尝试解析为JSON
                let details;
                if (typeof commandExecutionDetails === 'string') {
                    details = JSON.parse(commandExecutionDetails);
                } else {
                    details = commandExecutionDetails;
                }

                // 检查是否包含代码异常信息
                if (Array.isArray(details)) {
                    return details.some(detail => {
                        // 检查error_type字段是否为代码异常类型
                        if (detail.error_type && codeExceptionTypes.includes(detail.error_type)) {
                            return true;
                        }
                        // 检查是否有exception_type或exception_message字段（这些是代码执行异常的特有字段）
                        if (detail.exception_type || detail.exception_message) {
                            return true;
                        }
                        // 检查error字段中是否包含代码异常类型（针对旧数据格式）
                        if (detail.error && typeof detail.error === 'string') {
                            const errorStr = detail.error.toLowerCase();
                            // 检查error字段中是否包含代码异常类型关键词
                            if (codeExceptionTypes.some(errorType => errorStr.includes(errorType))) {
                                return true;
                            }
                            // 检查是否包含代码执行错误的特征字符串
                            if (errorStr.includes('代码执行错误') || errorStr.includes('traceback') ||
                                errorStr.includes('exception')) {
                                return true;
                            }
                        }
                        return false;
                    });
                } else if (details && typeof details === 'object') {
                    // 如果是单个对象，检查代码异常字段
                    if (details.error_type && codeExceptionTypes.includes(details.error_type)) {
                        return true;
                    }
                    // 检查是否有exception_type或exception_message字段
                    if (details.exception_type || details.exception_message) {
                        return true;
                    }
                    // 检查error字段中是否包含代码异常类型（针对旧数据格式）
                    if (details.error && typeof details.error === 'string') {
                        const errorStr = details.error.toLowerCase();
                        // 检查error字段中是否包含代码异常类型关键词
                        if (codeExceptionTypes.some(errorType => errorStr.includes(errorType))) {
                            return true;
                        }
                        // 检查是否包含代码执行错误的特征字符串
                        if (errorStr.includes('代码执行错误') || errorStr.includes('traceback') ||
                            errorStr.includes('exception')) {
                            return true;
                        }
                    }
                    return false;
                }
            } catch (e) {
                // JSON解析失败，使用字符串匹配检查代码异常
                const detailsStr = commandExecutionDetails.toString().toLowerCase();

                // 检查exception相关字段
                if (detailsStr.includes('"exception_type"') || detailsStr.includes('"exception_message"')) {
                    return true;
                }

                // 检查代码异常类型（使用正则表达式匹配error_type字段）
                if (codeExceptionTypes.some(errorType => {
                    const pattern = new RegExp(`"error_type"\\s*:\\s*"${errorType}"`);
                    return pattern.test(detailsStr);
                })) {
                    return true;
                }

                // 检查error字段中是否包含代码异常类型关键词
                if (codeExceptionTypes.some(errorType => detailsStr.includes(errorType))) {
                    return true;
                }

                // 检查是否包含代码执行错误的特征字符串
                if (detailsStr.includes('代码执行错误') || detailsStr.includes('traceback') ||
                    detailsStr.includes('exception') || detailsStr.includes('error:')) {
                    return true;
                }
            }

            return false;
        }

        // 检查命令执行详情中是否包含失败的命令或异常（用于回合筛选）
        function hasFailedCommandInDetails(commandExecutionDetails) {
            if (!commandExecutionDetails) {
                return false;
            }

            try {
                // 如果是字符串，尝试解析为JSON
                let details;
                if (typeof commandExecutionDetails === 'string') {
                    details = JSON.parse(commandExecutionDetails);
                } else {
                    details = commandExecutionDetails;
                }

                // 检查是否包含错误信息
                if (Array.isArray(details)) {
                    return details.some(detail =>
                        detail.success === false ||
                        detail.isError === true ||  // 添加对isError字段的检查
                        detail.exception_type ||
                        detail.exception_message ||
                        detail.error_type ||
                        detail.error  // 添加对error字段的检查
                    );
                } else if (details && typeof details === 'object') {
                    // 如果是单个对象，检查success字段或异常字段
                    return details.success === false ||
                           details.isError === true ||  // 添加对isError字段的检查
                           details.exception_type ||
                           details.exception_message ||
                           details.error_type ||
                           details.error;  // 添加对error字段的检查
                }
            } catch (e) {
                // JSON解析失败，使用字符串匹配（对应Python的icontains）
                const detailsStr = commandExecutionDetails.toString().toLowerCase();
                return detailsStr.includes('"success": false') ||
                       detailsStr.includes('"success":false') ||
                       detailsStr.includes('"iserror": true') ||  // 添加对isError的字符串匹配
                       detailsStr.includes('"iserror":true') ||
                       detailsStr.includes('"exception_type"') ||
                       detailsStr.includes('"exception_message"') ||
                       detailsStr.includes('"error_type"') ||
                       detailsStr.includes('"error"');  // 添加对error字段的字符串匹配
            }

            return false;
        }


        // 执行统计功能
        function initExecutionStats() {
            // 只在战斗完成时加载执行统计
            if ('{{ battle.status }}' === 'finished') {
                loadBattleStats();
                loadExecutionStats();

                // 绑定按钮事件
                const viewDetailsBtn = document.getElementById('btn-view-execution-details');
                const downloadBattleReportBtn = document.getElementById('btn-download-battle-report');
                const downloadLogBtn = document.getElementById('btn-download-log');

                if (viewDetailsBtn) {
                    viewDetailsBtn.addEventListener('click', toggleExecutionDetails);
                }

                if (downloadBattleReportBtn) {
                    downloadBattleReportBtn.addEventListener('click', downloadBattleReport);
                }

                if (downloadLogBtn) {
                    downloadLogBtn.addEventListener('click', downloadExecutionLog);
                }
            }
        }

        // 处理错误字符串的工具函数
        function processErrorMessage(errorMsg) {
            if (!errorMsg) return '';

            // 转换为字符串并去除首尾空格
            let processedMsg = errorMsg.toString().trim();

            // 简化文件路径
            processedMsg = processedMsg.replace(/File\s+"[^"]*\/([^/"]+\/[^/"]+\/[^"]+.py)"/g, 'File ".../$1"');

            // 替换换行符为HTML换行
            processedMsg = processedMsg.replace(/\\n/g, '<br>').replace(/\n/g, '<br>');

            return processedMsg;
        }

        // 生成错误内容HTML的工具函数
        function generateErrorContent(detail) {
            if (!detail.isError || !detail.error) {
                return '';
            }

            const errorMsg = processErrorMessage(detail.error);
            const isErrStack = detail.error.toString().includes('\n');

            if (isErrStack) {
                return `<pre class="error-stack-content">${errorMsg}</pre>`;
            } else {
                return `<code>${JSON.stringify(detail.command)}</code><div class="error-info text-danger"><strong>错误:</strong> ${errorMsg}</div>`;
            }
        }

        // 加载指定区间的回合详情数据
        function loadRangeRoundsData(startRound, endRound) {
            // 获取当前筛选条件
            const roundFilter = document.getElementById('round-filter');
            const filterValue = roundFilter ? roundFilter.value : '';

            // 使用带筛选条件的加载函数
            loadRangeRoundsDataWithFilter(startRound, endRound, filterValue);
        }

        // 显示回合详情数据
        function displayRangeRoundsData(rounds, battleData) {
            const rangeRoundsList = document.getElementById('range-rounds-list');
            const rangeSummaryText = document.getElementById('range-summary-text');
            const controlBar = document.getElementById('rounds-control-bar');

            if (!rounds || rounds.length === 0) {
                rangeRoundsList.innerHTML = `
                        <div class="alert alert-info">
                            <i class="fas fa-info-circle"></i> 选定区间内没有回合数据
                        </div>
                    `;
                // 更新摘要文本为0个回合
                if (rangeSummaryText) {
                    rangeSummaryText.textContent = '共 0 个回合';
                }
                // 隐藏控制栏
                if (controlBar) {
                    controlBar.style.display = 'none';
                }
                return;
            }

            // 更新摘要文本显示实际回合数
            if (rangeSummaryText) {
                rangeSummaryText.textContent = `共 ${rounds.length} 个回合`;
            }

            // 显示控制栏
            if (controlBar) {
                controlBar.style.display = 'flex';
            }

            // 保存数据并重置显示计数
            currentRoundsData = rounds;
            currentDisplayedCount = 0;

            // 清空容器并显示第一页
            rangeRoundsList.innerHTML = '';
            displayNextPage();
        }

        // 显示下一页回合数据
        window.displayNextPage = function displayNextPage() {
            const rangeRoundsList = document.getElementById('range-rounds-list');
            const startIndex = currentDisplayedCount;
            const endIndex = Math.min(startIndex + ROUNDS_PER_PAGE, currentRoundsData.length);

            let html = '';
            for (let i = startIndex; i < endIndex; i++) {
                const round = currentRoundsData[i];

                // 计算回合统计信息
                const p1Success = round.player1_successful_commands || 0;
                const p1Failed = round.player1_failed_commands || 0;
                const p2Success = round.player2_successful_commands || 0;
                const p2Failed = round.player2_failed_commands || 0;
                const totalCommands = p1Success + p1Failed + p2Success + p2Failed;
                const totalErrors = p1Failed + p2Failed;

                html += `
                        <div class="round-item mb-3 border rounded" data-round="${round.round_number}">
                            <div class="round-header" onclick="toggleRoundCollapse(${round.round_number})">
                                <div class="round-summary">
                                    <div class="round-summary-left">
                                        <i class="fas fa-chevron-down collapse-icon"></i>
                                        <h6 class="mb-0"><i class="fas fa-clock"></i> 第 ${round.round_number} 回合</h6>
                                        <div class="round-stats">
                                            <div class="round-stat success" title="成功执行的命令数量">
                                                <i class="fas fa-check-circle"></i>
                                                <span>${p1Success + p2Success}</span>
                                            </div>
                                            <div class="round-stat failed" title="执行失败的命令数量">
                                                <i class="fas fa-times-circle"></i>
                                                <span>${totalErrors}</span>
                                            </div>
                                        </div>
                                    </div>
                                    <div class="round-summary-right">
                                        <small class="text-muted">${round.timestamp}</small>
                                    </div>
                                </div>
                            </div>
                            <div class="round-content expanded" id="round-content-${round.round_number}">
                                <div class="p-3">

                            <div class="row">
                                <div class="col-md-6">
                                    <div class="d-flex justify-content-between align-items-center">
                                        <h6 class="text-danger mb-0">${battleData.player1.username}</h6>
                                        ${round.player1_battle_state && Object.keys(round.player1_battle_state).length > 0 ?
                                            `<button class="btn btn-sm btn-outline-primary download-battle-state"
                                                    data-round="${round.round_number}"
                                                    data-player="player1"
                                                    data-name="${battleData.player1.username}">
                                                <i class="fas fa-download"></i> 下载本回合输入状态
                                            </button>` : ''
                                        }
                                    </div>
                                    <div class="mb-2">
                                        <small class="text-success">成功命令: ${round.player1_successful_commands}</small> |
                                        <small class="text-danger">失败命令: ${round.player1_failed_commands}</small>
                                    </div>
                                    ${round.player1_command_execution_details && round.player1_command_execution_details.length > 0 ?
                        '<div class="actions-list">' + round.player1_command_execution_details.map((detail, index) => {
                            const statusClass = detail.isError ? 'failed' : 'success';

                            // 处理undefined命令的显示
                            const isUndefinedCommand = detail.command === undefined || detail.command === null ||
                                                    (typeof detail.command === 'string' && detail.command.trim() === 'undefined');

                            // 构建实体状态信息
                            let entityInfo = '';
                            if (detail.selfExecutionState) {
                                entityInfo += `<div class="entity-state"><strong>Self:</strong> ID ${detail.selfExecutionState.id} | ${detail.selfExecutionState.name} | 位置 ( ${detail.selfExecutionState.position.x}, ${detail.selfExecutionState.position.y} ) | 血量 ${detail.selfExecutionState.hp}</div>`;
                            }
                            if (detail.targetExecutionState) {
                                entityInfo += `<div class="entity-state"><strong>Target:</strong> ID ${detail.targetExecutionState.id} | ${detail.targetExecutionState.name} | 位置 ( ${detail.targetExecutionState.position.x}, ${detail.targetExecutionState.position.y} ) | 血量 ${detail.targetExecutionState.hp}</div>`;
                            }

                            // 优化错误信息显示
                            let content = '';
                            if (detail.isError && detail.error) {
                                content = generateErrorContent(detail);
                            } else if (!isUndefinedCommand) {
                                // 非undefined命令且无错误时，显示命令信息
                                content = `<div class="command-info"><code>${JSON.stringify(detail.command)}</code></div>`;
                            }

                            // 如果没有任何有效内容，则不显示该项
                            if (!content && !entityInfo) {
                                return '';
                            }

                            return `<div class="action-item small ${statusClass} mb-2" style="position: relative;">
                                        <div class="command-number" style="position: absolute; top: 5px; right: 8px; font-weight: bold; color: white; font-size: 12px; background: rgba(128,128,128,0.6); padding: 2px 6px; border-radius: 10px;">${index + 1}</div>
                                        ${content}
                                        ${entityInfo}
                                    </div>`;
                        }).join('') + '</div>' :
                        '<div class="text-muted small">无命令</div>'
                    }
                                </div>

                                <div class="col-md-6">
                                    <div class="d-flex justify-content-between align-items-center">
                                        <h6 class="text-primary mb-0">${battleData.player2.username}</h6>
                                        ${round.player2_battle_state && Object.keys(round.player2_battle_state).length > 0 ?
                                            `<button class="btn btn-sm btn-outline-primary download-battle-state"
                                                    data-round="${round.round_number}"
                                                    data-player="player2"
                                                    data-name="${battleData.player2.username}">
                                                <i class="fas fa-download"></i> 下载本回合输入状态
                                            </button>` : ''
                                        }
                                    </div>
                                    <div class="mb-2">
                                        <small class="text-success">成功命令: ${round.player2_successful_commands}</small> |
                                        <small class="text-danger">失败命令: ${round.player2_failed_commands}</small>
                                    </div>
                                    ${round.player2_command_execution_details && round.player2_command_execution_details.length > 0 ?
                        '<div class="actions-list">' + round.player2_command_execution_details.map((detail, index) => {
                            const statusClass = detail.isError ? 'failed' : 'success';

                            // 处理undefined命令的显示
                            const isUndefinedCommand = detail.command === undefined || detail.command === null ||
                                                    (typeof detail.command === 'string' && detail.command.trim() === 'undefined');

                            // 构建实体状态信息
                            let entityInfo = '';
                            if (detail.selfExecutionState) {
                                entityInfo += `<div class="entity-state"><strong>Self:</strong> ID ${detail.selfExecutionState.id} | ${detail.selfExecutionState.name} | 位置 ( ${detail.selfExecutionState.position.x}, ${detail.selfExecutionState.position.y} ) | 血量 ${detail.selfExecutionState.hp}</div>`;
                            }
                            if (detail.targetExecutionState) {
                                entityInfo += `<div class="entity-state"><strong>Target:</strong> ID ${detail.targetExecutionState.id} | ${detail.targetExecutionState.name} | 位置 ( ${detail.targetExecutionState.position.x}, ${detail.targetExecutionState.position.y} ) | 血量 ${detail.targetExecutionState.hp}</div>`;
                            }

                            // 优化错误信息显示
                            let content = '';
                            if (detail.isError && detail.error) {
                                content = generateErrorContent(detail);
                            } else if (!isUndefinedCommand) {
                                // 非undefined命令且无错误时，显示命令信息
                                content = `<div class="command-info"><code>${JSON.stringify(detail.command)}</code></div>`;
                            }

                            // 如果没有任何有效内容，则不显示该项
                            if (!content && !entityInfo) {
                                return '';
                            }

                            return `<div class="action-item small ${statusClass} mb-2" style="position: relative;">
                                        <div class="command-number" style="position: absolute; top: 5px; right: 8px; font-weight: bold; color: white; font-size: 12px; background: rgba(128,128,128,0.6); padding: 2px 6px; border-radius: 10px;">${index + 1}</div>
                                        ${content}
                                        ${entityInfo}
                                    </div>`;
                        }).join('') + '</div>' :
                        '<div class="text-muted small">无命令</div>'
                    }
                                </div>
                            </div>
                                </div>
                            </div>
                        </div>
                    `;
            }

            // 将新内容追加到现有内容后面
            const tempDiv = document.createElement('div');
            tempDiv.innerHTML = html;
            while (tempDiv.firstChild) {
                rangeRoundsList.appendChild(tempDiv.firstChild);
            }

            // 更新显示计数
            currentDisplayedCount = endIndex;

            // 添加或更新"加载更多"按钮
            updateLoadMoreButton();
        }

        // 更新"加载更多"按钮
        function updateLoadMoreButton() {
            const rangeRoundsList = document.getElementById('range-rounds-list');
            const existingButton = document.getElementById('load-more-rounds');

            // 移除现有按钮
            if (existingButton) {
                existingButton.remove();
            }

            // 如果还有更多数据，添加"加载更多"按钮
            if (currentDisplayedCount < currentRoundsData.length) {
                const loadMoreButton = document.createElement('div');
                loadMoreButton.id = 'load-more-rounds';
                loadMoreButton.className = 'text-center mt-3';
                loadMoreButton.innerHTML = `
                    <button class="btn btn-outline-primary" onclick="window.displayNextPage()">
                        <i class="fas fa-chevron-down"></i> 加载更多回合 (${currentDisplayedCount}/${currentRoundsData.length})
                    </button>
                `;
                rangeRoundsList.appendChild(loadMoreButton);
            } else if (currentRoundsData.length > ROUNDS_PER_PAGE) {
                // 显示完成提示
                const completeDiv = document.createElement('div');
                completeDiv.className = 'text-center mt-3 text-muted';
                completeDiv.innerHTML = `<small><i class="fas fa-check"></i> 已显示全部 ${currentRoundsData.length} 个回合</small>`;
                rangeRoundsList.appendChild(completeDiv);
            }
        }

        // 加载战斗统计数据
        function loadBattleStats() {
            fetch(`/battles/api/${battleId}/battle-stats/`)
                .then(response => response.json())
                .then(data => {
                    if (data.status === 'success') {
                        updateBattleStatsDisplay(data.data);
                    } else {
                        console.error('获取战斗统计失败:', data.error);
                    }
                })
                .catch(error => {
                    console.error('加载战斗统计时出错:', error);
                });
        }

        // 加载执行统计数据
        function loadExecutionStats(rounds = []) {
            fetch(`/battles/api/${battleId}/execution-stats/`)
                .then(response => response.json())
                .then(data => {
                    if (data.status === 'success') {
                        updateExecutionStatsDisplay(data.data, rounds);
                    } else {
                        console.error('获取执行统计失败:', data.error);
                        // 显示错误状态
                        updateExecutionStatsDisplay({}, rounds);
                    }
                })
                .catch(error => {
                    console.error('加载执行统计时出错:', error);
                    // 显示错误状态
                    updateExecutionStatsDisplay({}, rounds);
                });
        }

        // 更新战斗统计显示
        function updateBattleStatsDisplay(stats) {
            // 更新玩家统计区域的简要信息
            const player1Summary = document.getElementById('player1-battle-summary');
            const player2Summary = document.getElementById('player2-battle-summary');

            if (player1Summary && stats.player1) {
                const p1 = stats.player1;
                player1Summary.innerHTML = `
                        <small class="d-block"><i class="fas fa-fire text-danger"></i> 击杀: ${p1.stats.kills}</small>
                        <small class="d-block"><i class="fas fa-skull text-warning"></i> 死亡: ${p1.stats.deaths}</small>
                        <small class="d-block"><i class="fas fa-bolt text-info"></i> 伤害: ${p1.stats.totalDamageDealt}</small>
                        <small class="d-block"><i class="fas fa-pills text-success"></i> 治疗: ${p1.stats.totalHealing || 0}</small>
                        <small class="d-block"><i class="fas fa-heart text-danger"></i> 基地血量: ${p1.baseHealth || 0}</small>
                        <small class="d-block"><i class="fas fa-gem text-light-blue"></i> RMB: ${p1.rmb}</small>
                    `;
            }

            if (player2Summary && stats.player2) {
                const p2 = stats.player2;
                player2Summary.innerHTML = `
                        <small class="d-block"><i class="fas fa-fire text-danger"></i> 击杀: ${p2.stats.kills}</small>
                        <small class="d-block"><i class="fas fa-skull text-warning"></i> 死亡: ${p2.stats.deaths}</small>
                        <small class="d-block"><i class="fas fa-bolt text-info"></i> 伤害: ${p2.stats.totalDamageDealt}</small>
                        <small class="d-block"><i class="fas fa-pills text-success"></i> 治疗: ${p2.stats.totalHealing || 0}</small>
                        <small class="d-block"><i class="fas fa-heart text-danger"></i> 基地血量: ${p2.baseHealth || 0}</small>
                        <small class="d-block"><i class="fas fa-gem text-light-blue"></i> RMB: ${p2.rmb}</small>
                    `;
            }

        }

        // 计算每个玩家第一次代码异常出现的回合号（区分代码异常和普通命令失败）
        function calculateCodeExceptionRounds(rounds = []) {
            const result = {
                player1: 0,
                player2: 0
            };

            for (let i = 0; i < rounds.length; i++) {
                const round = rounds[i];

                // 检查玩家1是否有代码异常
                const p1HasException = hasCodeExecutionExceptionInDetails(round.player1_command_execution_details);
                if (p1HasException) {
                    result.player1++; // 累计异常数量
                }

                // 检查玩家2是否有代码异常
                const p2HasException = hasCodeExecutionExceptionInDetails(round.player2_command_execution_details);
                if (p2HasException) {
                    result.player2++; // 累计异常数量
                }
            }

            return result;
        }


        // 更新执行统计显示
        function updateExecutionStatsDisplay(stats, rounds = []) {
            // 计算每个玩家的异常总数量
            const exceptionRounds = calculateCodeExceptionRounds(rounds);
            const player1ExceptionDisplay = exceptionRounds.player1 > 0 ?
                `${exceptionRounds.player1}次` : '无';
            const player2ExceptionDisplay = exceptionRounds.player2 > 0 ?
                `${exceptionRounds.player2}次` : '无';

            // 更新详细统计区域
            const player1Details = document.getElementById('player1-detailed-stats');
            const player2Details = document.getElementById('player2-detailed-stats');

            if (player1Details && stats.player1) {
                const p1 = stats.player1;
                player1Details.innerHTML = `
                        <div class="stat-row">
                            <span class="stat-label">总命令数:</span>
                            <span class="stat-value">${p1.total_commands}</span>
                        </div>
                        <div class="stat-row">
                            <span class="stat-label">成功命令:</span>
                            <span class="stat-value text-success">${p1.successful_commands}</span>
                        </div>
                        <div class="stat-row">
                            <span class="stat-label">失败命令:</span>
                            <span class="stat-value text-danger">${p1.failed_commands}</span>
                        </div>
                        <div class="stat-row">
                            <span class="stat-label">成功率:</span>
                            <span class="stat-value">${p1.success_rate.toFixed(2)}%</span>
                        </div>
                        <div class="stat-row">
                            <span class="stat-label">异常总数:</span>
                            <span class="stat-value text-warning">${player1ExceptionDisplay}</span>
                        </div>
                    `;
            } else if (player1Details) {
                // 如果没有统计数据，显示无数据状态
                player1Details.innerHTML = '<div class="text-muted">暂无统计数据</div>';
            }

            if (player2Details && stats.player2) {
                const p2 = stats.player2;
                player2Details.innerHTML = `
                        <div class="stat-row">
                            <span class="stat-label">总命令数:</span>
                            <span class="stat-value">${p2.total_commands}</span>
                        </div>
                        <div class="stat-row">
                            <span class="stat-label">成功命令:</span>
                            <span class="stat-value text-success">${p2.successful_commands}</span>
                        </div>
                        <div class="stat-row">
                            <span class="stat-label">失败命令:</span>
                            <span class="stat-value text-danger">${p2.failed_commands}</span>
                        </div>
                        <div class="stat-row">
                            <span class="stat-label">成功率:</span>
                            <span class="stat-value">${p2.success_rate.toFixed(2)}%</span>
                        </div>
                        <div class="stat-row">
                            <span class="stat-label">异常总数:</span>
                            <span class="stat-value text-warning">${player2ExceptionDisplay}</span>
                        </div>
                    `;
            } else if (player2Details) {
                // 如果没有统计数据，显示无数据状态
                player2Details.innerHTML = '<div class="text-muted">暂无统计数据</div>';
            }

            // 存储失败命令详情以供后续显示
            window.executionStats = stats;
        }

        // 切换显示执行详情
        function toggleExecutionDetails() {
            // 显示失败命令详情模态框
            if (window.executionStats) {
                displayFailedCommands(window.executionStats);
            }

            // 打开模态框 - 兼容不同版本的Bootstrap
            const modalElement = document.getElementById('executionDetailsModal');
            if (!modalElement) {
                console.error('模态框元素未找到: executionDetailsModal');
                return;
            }

            if (typeof bootstrap !== 'undefined' && bootstrap.Modal) {
                // Bootstrap 5
                const modal = new bootstrap.Modal(modalElement);
                modal.show();
            } else if (typeof $ !== 'undefined' && $.fn.modal) {
                // Bootstrap 4 with jQuery
                $(modalElement).modal('show');
            } else {
                // 降级处理：直接显示模态框
                modalElement.style.display = 'block';
                modalElement.classList.add('show');
                document.body.classList.add('modal-open');

                // 添加背景遮罩
                const backdrop = document.createElement('div');
                backdrop.className = 'modal-backdrop fade show';
                backdrop.id = 'modal-backdrop-custom';
                document.body.appendChild(backdrop);
            }
        }

        // 显示失败命令详情
        function displayFailedCommands(stats) {
            const player1Failed = document.getElementById('player1-failed-commands');
            const player2Failed = document.getElementById('player2-failed-commands');
            const player1FailedModal = document.getElementById('player1-failed-commands-modal');
            const player2FailedModal = document.getElementById('player2-failed-commands-modal');

            function formatFailedCommand(detail, index) {
                let formattedDetail;
                try {
                    // 尝试解析为JSON对象
                    if (typeof detail === 'string') {
                        formattedDetail = JSON.parse(detail);
                    } else {
                        formattedDetail = detail;
                    }

                    // 提取command部分 - 支持多种数据结构
                    let commandContent = null;

                    // 检查是否是CommandExecutionDetailModel结构（包含command字段）
                    if (formattedDetail.command) {
                        commandContent = formattedDetail.command;
                    }
                    // 检查是否是FailCommandModel结构（直接包含命令数据）
                    else if (formattedDetail.type || formattedDetail.player) {
                        // 这可能是一个命令对象本身
                        commandContent = formattedDetail;
                    }
                    // 检查其他可能的字段名
                    else if (formattedDetail.cmd) {
                        commandContent = formattedDetail.cmd;
                    }
                    else if (formattedDetail.data && formattedDetail.data.command) {
                        commandContent = formattedDetail.data.command;
                    }
                    else if (formattedDetail.original_command) {
                        commandContent = formattedDetail.original_command;
                    }

                    // 格式化command内容
                    const commandString = commandContent ?
                        (typeof commandContent === 'string' ? commandContent : JSON.stringify(commandContent, null, 2)) :
                        '未找到命令内容';

                    // 获取错误信息
                    const errorMessage = formattedDetail.error || '未知错误';

                    // 获取回合信息
                    const roundInfo = formattedDetail.round || (commandContent && commandContent.round) || 'N/A';

                    return `
                        <div class="failed-command-item">
                            <div class="failed-command-header">
                                <small class="text-muted">#${index + 1}</small>
                                <small class="text-info">回合: ${roundInfo}</small>
                                ${formattedDetail.timestamp ? `<small class="text-muted">${new Date(formattedDetail.timestamp).toLocaleString()}</small>` : ''}
                            </div>
                            <div class="failed-command-content">
                                <div class="command-error mb-2">
                                    <strong class="text-warning">错误信息:</strong>
                                    <span class="error-message">${errorMessage}</span>
                                </div>
                                <div class="command-details">
                                    <strong class="text-info">命令内容:</strong>
                                    <pre class="json-display"><code>${commandString}</code></pre>
                                </div>
                            </div>
                        </div>
                    `;
                } catch (e) {
                    console.error('解析失败命令详情时出错:', e, detail);
                    // 如果不是JSON格式，直接显示原始内容
                    return `
                        <div class="failed-command-item">
                            <div class="failed-command-header">
                                <small class="text-muted">#${index + 1}</small>
                            </div>
                            <div class="failed-command-content">
                                <div class="alert alert-warning">
                                    <strong>解析错误:</strong> 无法解析失败命令数据格式
                                </div>
                                <pre class="raw-display"><code>${typeof detail === 'string' ? detail : JSON.stringify(detail, null, 2)}</code></pre>
                            </div>
                        </div>
                    `;
                }
            }

            if (stats.player1.failed_details) {
                const details = stats.player1.failed_details;
                const content = details.length > 0 ? `
                            <h6 class="text-primary">{{ battle.player1.username }} 失败命令 (${details.length})</h6>
                            <div class="failed-commands-content">
                                ${details.map((detail, index) => formatFailedCommand(detail, index)).join('')}
                            </div>
                        ` : '<p class="text-muted">无失败命令</p>';

                if (player1Failed) player1Failed.innerHTML = content;
                if (player1FailedModal) player1FailedModal.innerHTML = content;
            }

            if (stats.player2.failed_details) {
                const details = stats.player2.failed_details;
                const content = details.length > 0 ? `
                            <h6 class="text-danger">{{ battle.player2.username }} 失败命令 (${details.length})</h6>
                            <div class="failed-commands-content">
                                ${details.map((detail, index) => formatFailedCommand(detail, index)).join('')}
                            </div>
                        ` : '<p class="text-muted">无失败命令</p>';

                if (player2Failed) player2Failed.innerHTML = content;
                if (player2FailedModal) player2FailedModal.innerHTML = content;
            }
        }

        // 下载日志
        function downloadExecutionLog() {
            // 下载debug日志
            const debugDownloadUrl = `/battles/api/${battleId}/debug-log-download/`;
            const debugLink = document.createElement('a');
            debugLink.href = debugDownloadUrl;
            debugLink.download = `battle_debug_${battleId}.log`;
            document.body.appendChild(debugLink);
            debugLink.click();
            document.body.removeChild(debugLink);

            // 稍微延迟后下载server日志，避免同时下载
            setTimeout(() => {
                const serverDownloadUrl = `/battles/api/${battleId}/server-log-download/`;
                const serverLink = document.createElement('a');
                serverLink.href = serverDownloadUrl;
                serverLink.download = `battle_server_${battleId}.log`;
                document.body.appendChild(serverLink);
                serverLink.click();
                document.body.removeChild(serverLink);
            }, 1000);
        }

        // 下载战报
        function downloadBattleReport() {
            const downloadUrl = `/battles/api/${battleId}/report-download/`;

            // 创建一个临时的下载链接
            const link = document.createElement('a');
            link.href = downloadUrl;
            link.download = `battle_${battleId}_report.txt`;
            document.body.appendChild(link);
            link.click();
            document.body.removeChild(link);
        }

        // 更新区间显示
        function updateRangeDisplay() {
            const startInput = document.getElementById('start-round');
            const endInput = document.getElementById('end-round');
            const rangeDisplay = document.getElementById('range-display');

            if (startInput && endInput && rangeDisplay) {
                const start = parseInt(startInput.value);
                const end = parseInt(endInput.value);
                rangeDisplay.innerHTML = `回合 ${start} - <span id="max-rounds-display">${end}</span>`;
            }
        }

        // 更新回合计数显示
        function updateRoundsCountDisplay() {
            const totalRoundsDisplay = document.getElementById('total-rounds-display');
            const maxRoundsDisplay = document.getElementById('max-rounds-display');

            if (totalRoundsDisplay && totalRounds > 0) {
                totalRoundsDisplay.textContent = totalRounds;
            }

            if (maxRoundsDisplay && totalRounds > 0) {
                maxRoundsDisplay.textContent = totalRounds;
            }

            // 更新滑块和输入框的最大值
            const startSlider = document.getElementById('start-slider');
            const endSlider = document.getElementById('end-slider');
            const startInput = document.getElementById('start-round');
            const endInput = document.getElementById('end-round');

            if (startSlider && totalRounds > 0) {
                startSlider.max = totalRounds;
            }
            if (endSlider && totalRounds > 0) {
                endSlider.max = totalRounds;
                endSlider.value = totalRounds;
            }
            if (startInput && totalRounds > 0) {
                startInput.max = totalRounds;
            }
            if (endInput && totalRounds > 0) {
                endInput.max = totalRounds;
                endInput.value = totalRounds;
            }
        }

        // 更新区间填充条
        function updateRangeFill() {
            const startSlider = document.getElementById('start-slider');
            const endSlider = document.getElementById('end-slider');
            const rangeFill = document.getElementById('range-fill');

            if (startSlider && endSlider && rangeFill) {
                const start = parseInt(startSlider.value);
                const end = parseInt(endSlider.value);
                const max = parseInt(startSlider.max);

                const startPercent = ((start - 1) / (max - 1)) * 100;
                const endPercent = ((end - 1) / (max - 1)) * 100;

                rangeFill.style.left = startPercent + '%';
                rangeFill.style.width = (endPercent - startPercent) + '%';
            }
        }

        // 下载失败命令函数
        function downloadFailedCommands() {
            try {

                // 从页面获取失败命令数据
                const player1Modal = document.getElementById('player1-failed-commands-modal');
                const player2Modal = document.getElementById('player2-failed-commands-modal');

                // 格式化命令内容为富文本格式
                function formatCommandContent(jsonData, rawData) {
                    let content = '';

                    if (jsonData) {
                        try {
                            // jsonData已经是从DOM中获取的JSON字符串，需要解析
                            const parsed = JSON.parse(jsonData);

                            // 尝试多种可能的命令字段名 - 与formatFailedCommand函数保持一致
                            let commandContent = null;

                            // 检查是否是CommandExecutionDetailModel结构（包含command字段）
                            if (parsed.command) {
                                commandContent = parsed.command;
                            }
                            // 检查是否是FailCommandModel结构（直接包含命令数据）
                            else if (parsed.type || parsed.player) {
                                // 这可能是一个命令对象本身
                                commandContent = parsed;
                            }
                            // 检查其他可能的字段名
                            else if (parsed.cmd) {
                                commandContent = parsed.cmd;
                            }
                            else if (parsed.data && parsed.data.command) {
                                commandContent = parsed.data.command;
                            }
                            else if (parsed.original_command) {
                                commandContent = parsed.original_command;
                            }

                            if (commandContent) {
                                content += '    命令内容:\n';
                                const formattedCommand = typeof commandContent === 'string' ? commandContent : JSON.stringify(commandContent, null, 2);
                                content += '      ' + formattedCommand.replace(/\n/g, '\n      ') + '\n';
                            } else {
                                // 如果没有找到命令内容，显示提示信息和原始数据用于调试
                                content += '    命令内容: 未找到命令内容\n';
                                content += '    原始数据结构:\n';
                                content += '      ' + JSON.stringify(parsed, null, 2).replace(/\n/g, '\n      ') + '\n';
                            }
                        } catch (e) {
                            console.error('解析失败命令JSON数据时出错:', e, jsonData);
                            content += '    命令内容: JSON解析失败\n';
                            content += '    原始数据: ' + jsonData + '\n';
                        }
                    } else if (rawData) {
                        content += '    原始命令数据:\n';
                        content += '      ' + rawData.replace(/\n/g, '\n      ') + '\n';
                    } else {
                        content += '    命令内容: 无数据\n';
                    }
                    return content;
                }

                // 递归格式化对象
                function formatObject(obj, indent = 0) {
                    const spaces = ' '.repeat(indent);
                    let result = '';

                    if (typeof obj === 'object' && obj !== null) {
                        if (Array.isArray(obj)) {
                            obj.forEach((item, index) => {
                                result += `${spaces}[${index}]: `;
                                if (typeof item === 'object') {
                                    result += '\n' + formatObject(item, indent + 2);
                                } else {
                                    result += item + '\n';
                                }
                            });
                        } else {
                            Object.keys(obj).forEach(key => {
                                result += `${spaces}${key}: `;
                                if (typeof obj[key] === 'object' && obj[key] !== null) {
                                    result += '\n' + formatObject(obj[key], indent + 2);
                                } else {
                                    result += obj[key] + '\n';
                                }
                            });
                        }
                    } else {
                        result += spaces + obj + '\n';
                    }

                    return result;
                }

                // 生成玩家失败命令文本
                function generatePlayerReport(playerModal, playerName) {
                    if (!playerModal) {
                        return null; // 没有模态框数据，返回null
                    }

                    const commandItems = playerModal.querySelectorAll('.failed-command-item');

                    if (commandItems.length === 0) {
                        return null; // 没有失败命令，返回null
                    }

                    let content = `玩家: ${playerName}\n`;
                    content += `战斗ID: ${battleId}\n`;
                    content += `导出时间: ${new Date().toLocaleString('zh-CN')}\n`;
                    content += '\n' + '='.repeat(50) + '\n\n';

                    commandItems.forEach((item, index) => {
                        const errorMsg = item.querySelector('.error-message');
                        const jsonDisplay = item.querySelector('.json-display');
                        const rawDisplay = item.querySelector('.raw-display');

                        content += `失败命令 #${index + 1}\n`;
                        content += '-'.repeat(30) + '\n';

                        if (errorMsg) {
                            content += `失败描述: ${errorMsg.textContent.trim()}\n\n`;
                        }

                        const jsonData = jsonDisplay ? jsonDisplay.textContent.trim() : '';
                        const rawData = rawDisplay ? rawDisplay.textContent.trim() : '';

                        if (jsonData || rawData) {
                            content += formatCommandContent(jsonData, rawData);
                        }

                        content += '\n';
                    });

                    return content;
                }

                // 生成并下载玩家报告（只有存在失败命令的玩家才导出）
                let downloadCount = 0;

                // 检查玩家1
                const player1Content = generatePlayerReport(player1Modal, '玩家1');
                if (player1Content) {
                    const player1Blob = new Blob([player1Content], { type: 'text/plain;charset=utf-8' });
                    const player1Url = URL.createObjectURL(player1Blob);
                    const player1Link = document.createElement('a');
                    player1Link.href = player1Url;
                    player1Link.download = `battle_${battleId}_player1_failed_commands.txt`;
                    document.body.appendChild(player1Link);
                    player1Link.click();
                    document.body.removeChild(player1Link);
                    URL.revokeObjectURL(player1Url);
                    downloadCount++;
                }

                // 检查玩家2
                const player2Content = generatePlayerReport(player2Modal, '玩家2');
                if (player2Content) {
                    const player2Blob = new Blob([player2Content], { type: 'text/plain;charset=utf-8' });
                    const player2Url = URL.createObjectURL(player2Blob);
                    const player2Link = document.createElement('a');
                    player2Link.href = player2Url;
                    player2Link.download = `battle_${battleId}_player2_failed_commands.txt`;
                    document.body.appendChild(player2Link);
                    player2Link.click();
                    document.body.removeChild(player2Link);
                    URL.revokeObjectURL(player2Url);
                    downloadCount++;
                }

                console.log('失败命令导出成功');

                // 显示成功提示
                if (downloadCount === 0) {
                    if (typeof showNotification === 'function') {
                        showNotification('没有失败命令需要导出', 'info');
                    } else {
                        alert('没有失败命令需要导出');
                    }
                } else {
                    if (typeof showNotification === 'function') {
                        showNotification(`失败命令已成功导出为${downloadCount}个文本文件`, 'success');
                    } else {
                        alert(`失败命令已成功导出为${downloadCount}个文本文件`);
                    }
                }

            } catch (error) {
                console.error('导出失败命令时出错:', error);

                // 显示错误提示
                if (typeof showNotification === 'function') {
                    showNotification('导出失败命令时出错: ' + error.message, 'error');
                } else {
                    alert('导出失败命令时出错: ' + error.message);
                }
            }
        }

        // 绑定模态框关闭事件（降级处理）
        const closeModalBtns = document.querySelectorAll('[data-bs-dismiss="modal"]');
        closeModalBtns.forEach(btn => {
            btn.addEventListener('click', function() {
                const modalElement = document.getElementById('executionDetailsModal');
                if (modalElement) {
                    modalElement.style.display = 'none';
                    modalElement.classList.remove('show');
                    document.body.classList.remove('modal-open');

                    // 移除背景遮罩
                    const backdrop = document.getElementById('modal-backdrop-custom');
                    if (backdrop) {
                        backdrop.remove();
                    }
                }
            });
        });

        // 点击背景遮罩关闭模态框
        document.addEventListener('click', function(e) {
            if (e.target && e.target.id === 'modal-backdrop-custom') {
                const modalElement = document.getElementById('executionDetailsModal');
                if (modalElement) {
                    modalElement.style.display = 'none';
                    modalElement.classList.remove('show');
                    document.body.classList.remove('modal-open');
                    e.target.remove();
                }
            }
        });

        // 绑定导出失败命令按钮事件
        const exportBtn = document.getElementById('exportFailedCommandsBtn');
        if (exportBtn) {
            exportBtn.addEventListener('click', downloadFailedCommands);
        }

        // 下载战斗状态函数
        function downloadBattleState(roundNumber, playerType, playerName) {
            // 从当前回合数据中获取对应的battle_state
            const round = currentRoundsData.find(r => r.round_number == roundNumber);
            if (!round) {
                alert('未找到回合数据');
                return;
            }

            const battleState = playerType === 'player1' ? round.player1_battle_state : round.player2_battle_state;

            if (!battleState || Object.keys(battleState).length === 0) {
                alert('该回合没有战斗状态数据');
                return;
            }

            // 格式化JSON数据
            const jsonContent = JSON.stringify(battleState, null, 2);

            // 创建Blob对象
            const blob = new Blob([jsonContent], { type: 'application/json' });

            // 创建下载链接
            const link = document.createElement('a');
            link.href = URL.createObjectURL(blob);
            link.download = `battle_${battleId}_round_${roundNumber}_${playerName}_state.json`;

            // 触发下载
            document.body.appendChild(link);
            link.click();
            document.body.removeChild(link);

            // 清理URL对象
            URL.revokeObjectURL(link.href);
        }

        // 使用事件委托为下载战斗状态按钮添加事件监听
        document.addEventListener('click', function(event) {
            if (event.target.closest('.download-battle-state')) {
                const button = event.target.closest('.download-battle-state');
                const roundNumber = button.dataset.round;
                const playerType = button.dataset.player;
                const playerName = button.dataset.name;
                downloadBattleState(roundNumber, playerType, playerName);
            }
        });

        // 页面加载完成后初始化
        document.addEventListener('DOMContentLoaded', () => {
            console.log('DOMContentLoaded事件触发');

            // 显示获胜信息
            displayVictoryMessage();
            console.log('获胜信息显示完成');

            // 首先初始化BattleBridge
            initBattleBridge();
            console.log('BattleBridge初始化完成');

            // 直接加载回放数据
            loadReplayData();
            console.log('回放数据加载完成');

            // 初始化时间轴显示
            initSimpleRangeSelector();
            console.log('时间轴显示初始化完成');

            // 自动应用初始区间选择，等待异步数据加载完成后自动显示
            const startInput = document.getElementById('start-round');
            const endInput = document.getElementById('end-round');
            if (startInput && endInput) {
                const startRound = parseInt(startInput.value) || 1;
                const endRound = parseInt(endInput.value) || totalRounds;
                // 不在这里调用loadRangeRoundsData，等待loadRoundsData完成后自动显示
                console.log(`初始区间设置: ${startRound} - ${endRound}，等待异步数据加载完成`);
            };

            // 初始化执行统计
            initExecutionStats();
            console.log('执行统计初始化完成');

            // 初始化回合筛选器
            initRoundFilter();
            console.log('回合筛选器初始化完成');

            // 初始化命令类型筛选器
            initCommandTypeFilter();
            console.log('命令类型筛选器初始化完成');

            // 监听来自iframe的postMessage事件
            window.addEventListener('message', function (event) {
                if (battleBridge) {
                    battleBridge.handleIframeMessage(event);
                }
            });

            // 监听全屏状态变化
            document.addEventListener('fullscreenchange', handleFullscreenChange);
            document.addEventListener('webkitfullscreenchange', handleFullscreenChange);
            document.addEventListener('msfullscreenchange', handleFullscreenChange);

            function handleFullscreenChange() {
                const isCurrentlyFullscreen = !!(
                    document.fullscreenElement ||
                    document.webkitFullscreenElement ||
                    document.msFullscreenElement
                );
                if (isCurrentlyFullscreen !== isFullscreen) {
                    isFullscreen = isCurrentlyFullscreen;
                    updateFullscreenButtons();
                }
            }
        });

        // 添加定时器检查iframeReady状态
        let checkCount = 0; // 添加检查次数计数器
        let checkInterval = 500; // 添加间隔
        let maxCheckCount = 60; // 最大检查次数
        const checkIframeReady = setInterval(() => {
            checkCount++;
            if (battleBridge && battleBridge.iframeReady) {
                // 启用回放按钮
                const btnStartReplay = document.getElementById('btn-start-replay');
                if (btnStartReplay) {
                    btnStartReplay.disabled = false;
                    btnStartReplay.innerHTML = '<i class="fas fa-play"></i> 开始回放';
                }
                // 清除定时器
                clearInterval(checkIframeReady);
                console.log(`iframe已准备就绪, 回放按钮已启用, 共检查了${checkCount}次`);
            }else {
                if (battleBridge.iframe) {
                    battleBridge.sendToIframe("ping pong");
                    // battleBridge.iframeReady = true;
                }
                console.log(`iframe未准备就绪, 继续检查, 当前是第${checkCount}次检查`);
                if (checkCount >= maxCheckCount) {
                    clearInterval(checkIframeReady);
                    console.log(`检查次数超过最大次数${maxCheckCount}，停止检查`);
                    // 显示超时提示
                    const timeoutMessage = document.getElementById('timeout-message');
                    if (timeoutMessage) {
                        timeoutMessage.style.display = 'block';
                    }
                }
            }
        }, checkInterval);

    })();

    // 回合折叠功能
    window.toggleRoundCollapse = function(roundNumber) {
        const roundContent = document.getElementById(`round-content-${roundNumber}`);
        const roundHeader = document.querySelector(`[data-round="${roundNumber}"] .round-header`);

        if (!roundContent || !roundHeader) return;

        const isCollapsed = roundContent.classList.contains('collapsed');

        if (isCollapsed) {
            // 展开
            roundContent.classList.remove('collapsed');
            roundContent.classList.add('expanded');
            roundHeader.classList.remove('collapsed');
        } else {
            // 折叠
            roundContent.classList.remove('expanded');
            roundContent.classList.add('collapsed');
            roundHeader.classList.add('collapsed');
        }
    };

    // 展开所有回合
    window.expandAllRounds = function() {
        const allRoundContents = document.querySelectorAll('.round-content');
        const allRoundHeaders = document.querySelectorAll('.round-header');

        allRoundContents.forEach(content => {
            content.classList.remove('collapsed');
            content.classList.add('expanded');
        });

        allRoundHeaders.forEach(header => {
            header.classList.remove('collapsed');
        });
    };

    // 折叠所有回合
    window.collapseAllRounds = function() {
        const allRoundContents = document.querySelectorAll('.round-content');
        const allRoundHeaders = document.querySelectorAll('.round-header');

        allRoundContents.forEach(content => {
            content.classList.remove('expanded');
            content.classList.add('collapsed');
        });

        allRoundHeaders.forEach(header => {
            header.classList.add('collapsed');
        });
    };

    // 绑定控制按钮事件
    document.addEventListener('DOMContentLoaded', function() {
        const expandAllBtn = document.getElementById('expand-all-rounds');
        const collapseAllBtn = document.getElementById('collapse-all-rounds');

        if (expandAllBtn) {
            expandAllBtn.addEventListener('click', expandAllRounds);
        }

        if (collapseAllBtn) {
            collapseAllBtn.addEventListener('click', collapseAllRounds);
        }
    });

</script>
{% endif %}

<!-- 回到顶部悬浮球 -->
<button class="back-to-top" id="backToTop" title="回到顶部">
    <i class="fas fa-chevron-up"></i>
</button>

<script>
    // 刷新按钮功能
    (function () {
        const refreshBtn = document.getElementById('refresh-battle');
        if (refreshBtn) {
            refreshBtn.addEventListener('click', function () {
                // 添加加载状态
                const icon = this.querySelector('i');
                const text = this.querySelector('span');
                const originalIcon = icon.className;
                const originalText = text.textContent;

                // 更新按钮状态
                icon.className = 'fas fa-spinner fa-spin';
                text.textContent = '刷新中...';
                this.disabled = true;

                // 刷新页面
                setTimeout(() => {
                    window.location.reload();
                }, 500);
            });
        }
    })();

    // 回到顶部功能
    (function () {
        const backToTopBtn = document.getElementById('backToTop');

        // 监听滚动事件
        window.addEventListener('scroll', function () {
            if (window.pageYOffset > 300) {
                backToTopBtn.classList.add('show');
            } else {
                backToTopBtn.classList.remove('show');
            }
        });

        // 点击回到顶部
        backToTopBtn.addEventListener('click', function () {
            window.scrollTo({
                top: 0,
                behavior: 'smooth',
            });
        });
    })();
</script>

{% endblock %}
